diff options
Diffstat (limited to 'core')
53 files changed, 1358 insertions, 291 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 53e6f34..541f413 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -990,6 +990,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case SHUTDOWN_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + boolean res = shutdown(data.readInt()); + reply.writeNoException(); + reply.writeInt(res ? 1 : 0); + return true; + } + case PEEK_SERVICE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); Intent service = Intent.CREATOR.createFromParcel(data); @@ -2160,5 +2168,19 @@ class ActivityManagerProxy implements IActivityManager return res; } + public boolean shutdown(int timeout) throws RemoteException + { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(timeout); + mRemote.transact(SHUTDOWN_TRANSACTION, data, reply, 0); + reply.readException(); + boolean res = reply.readInt() != 0; + 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 index dfa3fa8..1e15d14 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -191,16 +191,11 @@ public final class ActivityThread { usePreloaded = false; DisplayMetrics newMetrics = new DisplayMetrics(); newMetrics.setTo(metrics); - float invertedScale = 1.0f / applicationScale; - newMetrics.density *= invertedScale; - newMetrics.xdpi *= invertedScale; - newMetrics.ydpi *= invertedScale; - newMetrics.widthPixels *= invertedScale; - newMetrics.heightPixels *= invertedScale; + float newDensity = metrics.density / applicationScale; + newMetrics.updateDensity(newDensity); metrics = newMetrics; } - //Log.i(TAG, "Resource:" + appDir + ", density " + newMetrics.density + ", orig density:" + - // metrics.density); + //Log.i(TAG, "Resource:" + appDir + ", display metrics=" + metrics); r = new Resources(assets, metrics, getConfiguration(), usePreloaded); //Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration()); // XXX need to remove entries when weak references go away @@ -316,18 +311,16 @@ public final class ActivityThread { float appScale = -1.0f; if (ai.supportsDensities != null) { - // TODO: precompute this in DisplayMetrics - float systemDensityDpi = metrics.density * DisplayMetrics.DEFAULT_DENSITY; int minDiff = Integer.MAX_VALUE; for (int density : ai.supportsDensities) { - int tmpDiff = (int) Math.abs(systemDensityDpi - density); + int tmpDiff = (int) Math.abs(DisplayMetrics.DEVICE_DENSITY - density); if (tmpDiff == 0) { appScale = 1.0f; break; } // prefer higher density (appScale>1.0), unless that's only option. if (tmpDiff < minDiff && appScale < 1.0f) { - appScale = systemDensityDpi / density; + appScale = DisplayMetrics.DEVICE_DENSITY / density; minDiff = tmpDiff; } } @@ -3482,6 +3475,8 @@ public final class ActivityThread { } mConfiguration.updateFrom(config); DisplayMetrics dm = getDisplayMetricsLocked(true); + DisplayMetrics appDm = new DisplayMetrics(); + appDm.setTo(dm); // set it for java, this also affects newly created Resources if (config.locale != null) { @@ -3501,7 +3496,11 @@ public final class ActivityThread { WeakReference<Resources> v = it.next(); Resources r = v.get(); if (r != null) { - r.updateConfiguration(config, dm); + // keep the original density based on application cale. + appDm.updateDensity(r.getDisplayMetrics().density); + r.updateConfiguration(config, appDm); + // reset + appDm.setTo(dm); //Log.i(TAG, "Updated app resources " + v.getKey() // + " " + r + ": " + r.getConfiguration()); } else { diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 2ac6160..56b29c1 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -16,7 +16,6 @@ package android.app; -import android.app.ActivityManager.MemoryInfo; import android.content.ComponentName; import android.content.ContentProviderNative; import android.content.IContentProvider; @@ -34,7 +33,6 @@ 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; @@ -225,6 +223,8 @@ public interface IActivityManager extends IInterface { public boolean profileControl(String process, boolean start, String path) throws RemoteException; + public boolean shutdown(int timeout) throws RemoteException; + /* * Private non-Binder interfaces */ @@ -370,4 +370,5 @@ public interface IActivityManager extends IInterface { int GET_DEVICE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+83; int PEEK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+84; int PROFILE_CONTROL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+85; + int SHUTDOWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+86; } diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 8fc2447..a174843 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -171,7 +171,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // having windows anchored by their parent but not clipped by them. ViewGroup.LayoutParams.FILL_PARENT); WindowManager.LayoutParams lp = theWindow.getAttributes(); - lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE; + lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; theWindow.setAttributes(lp); // get the view elements for local access @@ -325,6 +325,14 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // show the dialog. this will call onStart(). if (!isShowing()) { + // First make sure the keyboard is showing (if needed), so that we get the right height + // for the dropdown to respect the IME. + if (getContext().getResources().getConfiguration().hardKeyboardHidden == + Configuration.HARDKEYBOARDHIDDEN_YES) { + InputMethodManager inputManager = (InputMethodManager) + getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + inputManager.showSoftInputUnchecked(0, null); + } show(); } @@ -531,9 +539,13 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS if (mGlobalSearchMode) { mSearchAutoComplete.setDropDownAlwaysVisible(true); // fill space until results come in mSearchAutoComplete.setDropDownDismissedOnCompletion(false); + mSearchAutoComplete.setDropDownBackgroundResource( + com.android.internal.R.drawable.search_dropdown_background); } else { mSearchAutoComplete.setDropDownAlwaysVisible(false); mSearchAutoComplete.setDropDownDismissedOnCompletion(true); + mSearchAutoComplete.setDropDownBackgroundResource( + com.android.internal.R.drawable.search_dropdown_background_apps); } // attach the suggestions adapter, if suggestions are available diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index 2d2f98a..3bf37c3 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -1182,15 +1182,35 @@ public class SearchManager * 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"; + public final static String SUGGEST_MIME_TYPE = + "vnd.android.cursor.dir/vnd.android.search.suggest"; /** + * Uri path for shortcut validation. This is the path that the search manager will use when + * querying your content provider to refresh a shortcutted suggestion result and to check if it + * is still valid. When asked, a source may return an up to date result, or no result. No + * result indicates the shortcut refers to a no longer valid sugggestion. + * + * @see #SUGGEST_COLUMN_SHORTCUT_ID + * + * @hide pending API council approval + */ + public final static String SUGGEST_URI_PATH_SHORTCUT = "search_suggest_shortcut"; + + /** + * MIME type for shortcut validation. You'll use this in your suggestions content provider + * in the getType() function. + * + * @hide pending API council approval + */ + public final static String SHORTCUT_MIME_TYPE = + "vnd.android.cursor.item/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"; @@ -1303,6 +1323,26 @@ public class SearchManager public final static String SUGGEST_COLUMN_QUERY = "suggest_intent_query"; /** + * Column name for suggestions cursor. <i>Optional.</i> This column is used to indicate whether + * a search suggestion should be stored as a shortcut, and whether it should be validated. If + * missing, the result will be stored as a shortcut and never validated. If set to + * {@link #SUGGEST_NEVER_MAKE_SHORTCUT}, the result will not be stored as a shortcut. + * Otherwise, the shortcut id will be used to check back for validation via + * {@link #SUGGEST_URI_PATH_SHORTCUT}. + * + * @hide Pending API council approval. + */ + public final static String SUGGEST_COLUMN_SHORTCUT_ID = "suggest_shortcut_id"; + + /** + * Column value for suggestion column {@link #SUGGEST_COLUMN_SHORTCUT_ID} when a suggestion + * should not be stored as a shortcut in global search. + * + * @hide Pending API council approval. + */ + public final static String SUGGEST_NEVER_MAKE_SHORTCUT = "_-1"; + + /** * If a suggestion has this value in {@link #SUGGEST_COLUMN_INTENT_ACTION}, * the search dialog will switch to a different suggestion source when the * suggestion is clicked. diff --git a/core/java/android/backup/BackupDataOutput.java b/core/java/android/backup/BackupDataOutput.java new file mode 100644 index 0000000..6c47f7e --- /dev/null +++ b/core/java/android/backup/BackupDataOutput.java @@ -0,0 +1,44 @@ +/* + * 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.backup; + +import android.content.Context; + +import java.io.FileDescriptor; + +public class BackupDataOutput { + /* package */ FileDescriptor fd; + + public static final int OP_UPDATE = 1; + public static final int OP_DELETE = 2; + + public BackupDataOutput(Context context, FileDescriptor fd) { + this.fd = fd; + } + + public void close() { + // do we close the fd? + } + public native void flush(); + public native void write(byte[] buffer); + public native void write(int oneByte); + public native void write(byte[] buffer, int offset, int count); + + public native void writeOperation(int op); + public native void writeKey(String key); +} + diff --git a/core/java/android/backup/FileBackupHelper.java b/core/java/android/backup/FileBackupHelper.java new file mode 100644 index 0000000..3b2122c --- /dev/null +++ b/core/java/android/backup/FileBackupHelper.java @@ -0,0 +1,68 @@ +/* + * 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.backup; + +import android.content.Context; +import android.os.ParcelFileDescriptor; + +import java.io.FileDescriptor; + +public class FileBackupHelper { + /** + * Based on oldSnapshot, determine which of the files from the application's data directory + * need to be backed up, write them to the data stream, and fill in newSnapshot with the + * state as it exists now. + */ + public static void performBackup(Context context, + ParcelFileDescriptor oldSnapshot, ParcelFileDescriptor newSnapshot, + BackupDataOutput data, String[] files) { + String basePath = context.getFilesDir().getAbsolutePath(); + performBackup_checked(basePath, oldSnapshot, newSnapshot, data, files); + } + + /** + * Check the parameters so the native code doens't have to throw all the exceptions + * since it's easier to do that from java. + */ + static void performBackup_checked(String basePath, + ParcelFileDescriptor oldSnapshot, ParcelFileDescriptor newSnapshot, + BackupDataOutput data, String[] files) { + if (newSnapshot == null) { + throw new NullPointerException("newSnapshot==null"); + } + if (data == null) { + throw new NullPointerException("data==null"); + } + if (data.fd == null) { + throw new NullPointerException("data.fd==null"); + } + if (files == null) { + throw new NullPointerException("files==null"); + } + + int err = performBackup_native(basePath, oldSnapshot.getFileDescriptor(), + newSnapshot.getFileDescriptor(), data.fd, files); + + if (err != 0) { + throw new RuntimeException("Backup failed"); // TODO: more here + } + } + + native private static int performBackup_native(String basePath, + FileDescriptor oldSnapshot, FileDescriptor newSnapshot, + FileDescriptor data, String[] files); +} diff --git a/core/java/android/backup/SharedPreferencesBackupHelper.java b/core/java/android/backup/SharedPreferencesBackupHelper.java new file mode 100644 index 0000000..e839bb4 --- /dev/null +++ b/core/java/android/backup/SharedPreferencesBackupHelper.java @@ -0,0 +1,40 @@ +/* + * 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.backup; + +import android.content.Context; +import android.os.ParcelFileDescriptor; + +import java.io.FileDescriptor; + +public class SharedPreferencesBackupHelper { + public static void performBackup(Context context, + ParcelFileDescriptor oldSnapshot, ParcelFileDescriptor newSnapshot, + BackupDataOutput data, String[] prefGroups) { + String basePath = "/xxx"; //context.getPreferencesDir(); + + // make filenames for the prefGroups + final int N = prefGroups.length; + String[] files = new String[N]; + for (int i=0; i<N; i++) { + files[i] = prefGroups[i] + ".xml"; + } + + FileBackupHelper.performBackup_checked(basePath, oldSnapshot, newSnapshot, data, files); + } +} + diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index b3e81d7..81f72ac 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -510,6 +510,7 @@ import java.util.Set; * <li> {@link #ACTION_BATTERY_CHANGED} * <li> {@link #ACTION_POWER_CONNECTED} * <li> {@link #ACTION_POWER_DISCONNECTED} + * <li> {@link #ACTION_SHUTDOWN} * </ul> * * <h3>Standard Categories</h3> @@ -1270,6 +1271,15 @@ public class Intent implements Parcelable { @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED"; /** + * Broadcast Action: Device is shutting down. + * This is broadcast when the device is being shut down (completely turned + * off, not sleeping). Once the broadcast is complete, the final shutdown + * will proceed and all unsaved data lost. Apps will not normally need + * to handle this, since the forground activity will be paused as well. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN"; + /** * Broadcast Action: Indicates low memory condition on the device */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @@ -1930,7 +1940,7 @@ public class Intent implements Parcelable { /** * 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 + * is brought 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 diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java index ade5f3d..4d2cce8 100644 --- a/core/java/android/content/SyncManager.java +++ b/core/java/android/content/SyncManager.java @@ -212,6 +212,14 @@ class SyncManager { } }; + private BroadcastReceiver mShutdownIntentReceiver = + new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + Log.w(TAG, "Writing sync state before shutdown..."); + getSyncStorageEngine().writeAllState(); + } + }; + 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; @@ -249,6 +257,10 @@ class SyncManager { intentFilter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); context.registerReceiver(mStorageIntentReceiver, intentFilter); + intentFilter = new IntentFilter(Intent.ACTION_SHUTDOWN); + intentFilter.setPriority(100); + context.registerReceiver(mShutdownIntentReceiver, intentFilter); + if (!factoryTest) { mNotificationMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java index 1587462..3827849 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -736,7 +736,7 @@ public class SyncStorageEngine extends Handler { } boolean writeStatisticsNow = false; - int day = getCurrentDay(); + int day = getCurrentDayLocked(); if (mDayStats[0] == null) { mDayStats[0] = new DayStats(day); } else if (day != mDayStats[0].day) { @@ -925,7 +925,7 @@ public class SyncStorageEngine extends Handler { } } - private int getCurrentDay() { + private int getCurrentDayLocked() { mCal.setTimeInMillis(System.currentTimeMillis()); final int dayOfYear = mCal.get(Calendar.DAY_OF_YEAR); if (mYear != mCal.get(Calendar.YEAR)) { @@ -1005,6 +1005,21 @@ public class SyncStorageEngine extends Handler { return status; } + public void writeAllState() { + synchronized (mAuthorities) { + // Account info is always written so no need to do it here. + + if (mNumPendingFinished > 0) { + // Only write these if they are out of date. + writePendingOperationsLocked(); + } + + // Just always write these... they are likely out of date. + writeStatusLocked(); + writeStatisticsLocked(); + } + } + /** * Read all account information back in to the initial engine state. */ diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 173057c..fa9ec6e 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -113,19 +113,25 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { */ public static final int FLAG_ALLOW_CLEAR_USER_DATA = 1<<6; - /** - * Value for {@link #flags}: default value for the corresponding ActivityInfo flag. - * {@hide} + * Value for {@link #flags}: this is set if this application has been + * install as an update to a built-in system application. */ public static final int FLAG_UPDATED_SYSTEM_APP = 1<<7; + + /** + * Value for {@link #flags}: this is set of the application has set + * its android:targetSdkVersion to something >= the current SDK version. + */ + public static final int FLAG_TARGETS_SDK = 1<<8; /** * 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}. + * {@link #FLAG_ALLOW_CLEAR_USER_DATA}, {@link #FLAG_UPDATED_SYSTEM_APP}, + * {@link #FLAG_TARGETS_SDK}. */ public int flags = 0; diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 9e06666..e2f0ce4 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -172,6 +172,14 @@ public abstract class PackageManager { public static final int GET_SUPPORTS_DENSITIES = 0x00008000; /** + * 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; + + /** * Permission check result: this is returned by {@link #checkPermission} * if the permission has been granted to the given package. */ @@ -219,14 +227,6 @@ public abstract class PackageManager { */ 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; @@ -355,6 +355,14 @@ public abstract class PackageManager { public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13; /** + * 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 newer than + * that required by the package. + */ + public static final int INSTALL_FAILED_NEWER_SDK = -14; + + /** * 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 diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index f9c4984..12df5bd 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -59,6 +59,7 @@ public class PackageParser { private String mArchiveSourcePath; private String[] mSeparateProcesses; private int mSdkVersion; + private String mSdkCodename; private int mParseError = PackageManager.INSTALL_SUCCEEDED; @@ -123,8 +124,9 @@ public class PackageParser { mSeparateProcesses = procs; } - public void setSdkVersion(int sdkVersion) { + public void setSdkVersion(int sdkVersion, String codename) { mSdkVersion = sdkVersion; + mSdkCodename = codename; } private static final boolean isPackageFilename(String name) { @@ -613,9 +615,9 @@ public class PackageParser { int type; final Package pkg = new Package(pkgName); - pkg.mSystem = (flags&PARSE_IS_SYSTEM) != 0; boolean foundApp = false; - + boolean targetsSdk = false; + TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifest); pkg.mVersionCode = sa.getInteger( @@ -721,19 +723,74 @@ public class PackageParser { XmlUtils.skipCurrentTag(parser); - } else if (tagName.equals("uses-sdk")) { + } 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); + int minVers = 0; + String minCode = null; + int targetVers = 0; + String targetCode = null; + + TypedValue val = sa.peekValue( + com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion); + if (val != null) { + if (val.type == TypedValue.TYPE_STRING && val.string != null) { + targetCode = minCode = val.string.toString(); + } else { + // If it's not a string, it's an integer. + minVers = val.data; + } + } + + val = sa.peekValue( + com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion); + if (val != null) { + if (val.type == TypedValue.TYPE_STRING && val.string != null) { + targetCode = minCode = val.string.toString(); + } else { + // If it's not a string, it's an integer. + targetVers = val.data; + } + } + + int maxVers = sa.getInt( + com.android.internal.R.styleable.AndroidManifestUsesSdk_maxSdkVersion, + mSdkVersion); sa.recycle(); - if (vers > mSdkVersion) { - outError[0] = "Requires newer sdk version #" + vers - + " (current version is #" + mSdkVersion + ")"; + if (targetCode != null) { + if (!targetCode.equals(mSdkCodename)) { + if (mSdkCodename != null) { + outError[0] = "Requires development platform " + targetCode + + " (current platform is " + mSdkCodename + ")"; + } else { + outError[0] = "Requires development platform " + targetCode + + " but this is a release platform."; + } + mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; + return null; + } + // If the code matches, it definitely targets this SDK. + targetsSdk = true; + } else if (targetVers >= mSdkVersion) { + // If they have explicitly targeted our current version + // or something after it, then note this. + targetsSdk = true; + } + + if (minVers > mSdkVersion) { + outError[0] = "Requires newer sdk version #" + minVers + + " (current version is #" + mSdkVersion + ")"; + mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; + return null; + } + + if (maxVers < mSdkVersion) { + outError[0] = "Requires older sdk version #" + maxVers + + " (current version is #" + mSdkVersion + ")"; mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; return null; } @@ -767,6 +824,10 @@ public class PackageParser { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY; } + if (targetsSdk) { + pkg.applicationInfo.flags |= ApplicationInfo.FLAG_TARGETS_SDK; + } + if (pkg.usesLibraries.size() > 0) { pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()]; pkg.usesLibraries.toArray(pkg.usesLibraryFiles); @@ -2133,9 +2194,6 @@ public class PackageParser { // 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; diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java index 6a560ce..fea63be 100755 --- a/core/java/android/inputmethodservice/Keyboard.java +++ b/core/java/android/inputmethodservice/Keyboard.java @@ -27,8 +27,7 @@ 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 android.util.DisplayMetrics; import java.io.IOException; import java.util.ArrayList; @@ -510,10 +509,11 @@ public class Keyboard { * @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(); + DisplayMetrics dm = context.getResources().getDisplayMetrics(); + mDisplayWidth = dm.widthPixels; + mDisplayHeight = dm.heightPixels; + //Log.v(TAG, "keyboard's display metrics:" + dm); + mDefaultHorizontalGap = 0; mDefaultWidth = mDisplayWidth / 10; mDefaultVerticalGap = 0; diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java index 65c9893..8b474d5 100755 --- a/core/java/android/inputmethodservice/KeyboardView.java +++ b/core/java/android/inputmethodservice/KeyboardView.java @@ -407,7 +407,7 @@ public class KeyboardView extends View implements View.OnClickListener { // Release buffer, just in case the new keyboard has a different size. // It will be reallocated on the next draw. mBuffer = null; - invalidateAll(); + invalidateAllKeys(); computeProximityThreshold(keyboard); mMiniKeyboardCache.clear(); // Not really necessary to do every time, but will free up views } @@ -431,7 +431,7 @@ public class KeyboardView extends View implements View.OnClickListener { if (mKeyboard != null) { if (mKeyboard.setShifted(shifted)) { // The whole keyboard probably needs to be redrawn - invalidateAll(); + invalidateAllKeys(); return true; } } @@ -573,7 +573,7 @@ public class KeyboardView extends View implements View.OnClickListener { if (mBuffer == null) { mBuffer = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); mCanvas = new Canvas(mBuffer); - invalidateAll(); + invalidateAllKeys(); } final Canvas canvas = mCanvas; canvas.clipRect(mDirtyRect, Op.REPLACE); @@ -874,13 +874,27 @@ public class KeyboardView extends View implements View.OnClickListener { mPreviewText.setVisibility(VISIBLE); } - private void invalidateAll() { + /** + * Requests a redraw of the entire keyboard. Calling {@link #invalidate} is not sufficient + * because the keyboard renders the keys to an off-screen buffer and an invalidate() only + * draws the cached buffer. + * @see #invalidateKey(int) + */ + public void invalidateAllKeys() { mDirtyRect.union(0, 0, getWidth(), getHeight()); mDrawPending = true; invalidate(); } - - private void invalidateKey(int keyIndex) { + + /** + * Invalidates a key so that it will be redrawn on the next repaint. Use this method if only + * one key is changing it's content. Any changes that affect the position or size of the key + * may not be honored. + * @param keyIndex the index of the key in the attached {@link Keyboard}. + * @see #invalidateAllKeys + */ + public void invalidateKey(int keyIndex) { + if (mKeys == null) return; if (keyIndex < 0 || keyIndex >= mKeys.length) { return; } @@ -991,7 +1005,7 @@ public class KeyboardView extends View implements View.OnClickListener { mPopupKeyboard.showAtLocation(this, Gravity.NO_GRAVITY, x, y); mMiniKeyboardOnScreen = true; //mMiniKeyboard.onTouchEvent(getTranslatedEvent(me)); - invalidateAll(); + invalidateAllKeys(); return true; } return false; @@ -1164,7 +1178,7 @@ public class KeyboardView extends View implements View.OnClickListener { if (mPopupKeyboard.isShowing()) { mPopupKeyboard.dismiss(); mMiniKeyboardOnScreen = false; - invalidateAll(); + invalidateAllKeys(); } } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 467c17f..5487c54 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -59,11 +59,47 @@ public class Build { 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. + * The user-visible SDK version of the framework in its raw String + * representation; use {@link #SDK_INT} instead. + * + * @deprecated Use {@link #SDK_INT} to easily get this as an integer. */ public static final String SDK = getString("ro.build.version.sdk"); + + /** + * The user-visible SDK version of the framework; its possible + * values are defined in {@link Build.VERSION_CODES}. + */ + public static final int SDK_INT = SystemProperties.getInt( + "ro.build.version.sdk", 0); + + /** + * The current development codename, or the string "REL" if this is + * a release build. + */ + public static final String CODENAME = getString("ro.build.version.codename"); } + /** + * Enumeration of the currently known SDK version codes. These are the + * values that can be found in {@link VERSION#SDK}. Version numbers + * increment monotonically with each official platform release. + */ + public static class VERSION_CODES { + /** + * October 2008: The original, first, version of Android. Yay! + */ + public static final int BASE = 1; + /** + * February 2009: First Android update, officially called 1.1. + */ + public static final int BASE_1_1 = 2; + /** + * May 2009: Android 1.5. + */ + public static final int CUPCAKE = 3; + } + /** The type of build, like "user" or "eng". */ public static final String TYPE = getString("ro.build.type"); diff --git a/core/java/android/os/Power.java b/core/java/android/os/Power.java index 47497e5..3679e47 100644 --- a/core/java/android/os/Power.java +++ b/core/java/android/os/Power.java @@ -80,10 +80,9 @@ public class Power public static native int setLastUserActivityTimeout(long ms); /** - * Turn the device off. - * - * This method is considered deprecated in favor of - * {@link android.policy.ShutdownThread.shutdownAfterDisablingRadio()}. + * Low-level function turn the device off immediately, without trying + * to be clean. Most people should use + * {@link android.internal.app.ShutdownThread} for a clean shutdown. * * @deprecated * @hide diff --git a/core/java/android/speech/IRecognitionService.aidl b/core/java/android/speech/IRecognitionService.aidl index 8f06976..36d12e9a 100644 --- a/core/java/android/speech/IRecognitionService.aidl +++ b/core/java/android/speech/IRecognitionService.aidl @@ -16,7 +16,7 @@ package android.speech; -import android.os.Bundle; +import android.content.Intent; import android.speech.IRecognitionListener; // A Service interface to speech recognition. Call startListening when @@ -26,7 +26,8 @@ import android.speech.IRecognitionListener; /** {@hide} */ interface IRecognitionService { // Start listening for speech. Can only call this from one thread at once. - void startListening(in Bundle recognitionParams, + // see RecognizerIntent.java for constants used to specify the intent. + void startListening(in Intent recognizerIntent, in IRecognitionListener listener); void cancel(); diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java index 9de4cbe..e4dd020 100644 --- a/core/java/android/util/DisplayMetrics.java +++ b/core/java/android/util/DisplayMetrics.java @@ -31,7 +31,11 @@ public class DisplayMetrics { */ public static final int DEFAULT_DENSITY = 160; - private static final int sLcdDensity = SystemProperties.getInt("ro.sf.lcd_density", + /** + * The device's density. + * @hide + */ + public static final int DEVICE_DENSITY = SystemProperties.getInt("ro.sf.lcd_density", DEFAULT_DENSITY); /** @@ -90,9 +94,29 @@ public class DisplayMetrics { public void setToDefaults() { widthPixels = 0; heightPixels = 0; - density = sLcdDensity / (float) DEFAULT_DENSITY; + density = DEVICE_DENSITY / (float) DEFAULT_DENSITY; scaledDensity = density; - xdpi = sLcdDensity; - ydpi = sLcdDensity; + xdpi = DEVICE_DENSITY; + ydpi = DEVICE_DENSITY; + } + + /** + * Set the display metrics' density and update parameters depend on it. + * @hide + */ + public void updateDensity(float newDensity) { + float ratio = newDensity / density; + density = newDensity; + scaledDensity = density; + widthPixels *= ratio; + heightPixels *= ratio; + xdpi *= ratio; + ydpi *= ratio; + } + + public String toString() { + return "DisplayMetrics{density=" + density + ", width=" + widthPixels + + ", height=" + heightPixels + ", scaledDensity=" + scaledDensity + + ", xdpi=" + xdpi + ", ydpi=" + ydpi + "}"; } } diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 0d55679..86261c4 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -228,8 +228,10 @@ public final class MotionEvent implements Parcelable { if (mHistory != null) { float[] history = mHistory; int length = history.length; - for (int i = 0; i < length; i++) { + for (int i = 0; i < length; i += 4) { history[i] *= scale; + history[i + 2] *= scale; + history[i + 3] *= scale; } } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index d042f28..335b43c 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -850,6 +850,28 @@ public class View implements Drawable.Callback, KeyEvent.Callback { public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000; /** + * View flag indicating whether this view was invalidated (fully or partially.) + * + * @hide + */ + static final int DIRTY = 0x20000000; + + /** + * View flag indicating whether this view was invalidated by an opaque + * invalidate request. + * + * @hide + */ + static final int DIRTY_OPAQUE = 0x40000000; + + /** + * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}. + * + * @hide + */ + static final int DIRTY_MASK = 0x60000000; + + /** * Use with {@link #focusSearch}. Move focus to the previous selectable * item. */ @@ -4522,6 +4544,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback { } /** + * Indicates whether this View is opaque. An opaque View guarantees that it will + * draw all the pixels overlapping its bounds using a fully opaque color. + * + * Subclasses of View should override this method whenever possible to indicate + * whether an instance is opaque. Opaque Views are treated in a special way by + * the View hierarchy, possibly allowing it to perform optimizations during + * invalidate/draw passes. + * + * @return True if this View is guaranteed to be fully opaque, false otherwise. + * + * @hide Pending API council approval + */ + @ViewDebug.ExportedProperty + public boolean isOpaque() { + return mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE; + } + + /** * @return A handler associated with the thread running the View. This * handler can be used to pump events in the UI events queue. */ @@ -5687,7 +5727,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { final int restoreCount = canvas.save(); canvas.translate(-mScrollX, -mScrollY); - mPrivateFlags |= DRAWN; + mPrivateFlags = (mPrivateFlags & ~DIRTY_MASK) | DRAWN; // Fast path for layouts with no backgrounds if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { @@ -5875,7 +5915,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW); } - mPrivateFlags |= DRAWN; + final boolean dirtyOpaque = (mPrivateFlags & DIRTY_MASK) == DIRTY_OPAQUE; + mPrivateFlags = (mPrivateFlags & ~DIRTY_MASK) | DRAWN; /* * Draw traversal performs several drawing steps which must be executed @@ -5892,22 +5933,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback { // 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 (!dirtyOpaque) { + 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 (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); + if ((scrollX | scrollY) == 0) { + background.draw(canvas); + } else { + canvas.translate(scrollX, scrollY); + background.draw(canvas); + canvas.translate(-scrollX, -scrollY); + } } } @@ -5917,7 +5960,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; if (!verticalEdges && !horizontalEdges) { // Step 3, draw the content - onDraw(canvas); + if (!dirtyOpaque) onDraw(canvas); // Step 4, draw the children dispatchDraw(canvas); @@ -6020,7 +6063,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { } // Step 3, draw the content - onDraw(canvas); + if (!dirtyOpaque) onDraw(canvas); // Step 4, draw the children dispatchDraw(canvas); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index e686d1c..31159d7 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -1796,7 +1796,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager boolean preventRequestLayout) { child.mParent = null; addViewInner(child, index, params, preventRequestLayout); - child.mPrivateFlags |= DRAWN; + child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK) | DRAWN; return true; } @@ -2210,7 +2210,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager addInArray(child, index); child.mParent = this; - child.mPrivateFlags |= DRAWN; + child.mPrivateFlags = (child.mPrivateFlags & ~DIRTY_MASK) | DRAWN; if (child.hasFocus()) { requestChildFocus(child, child.findFocus()); @@ -2320,15 +2320,33 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // ourselves and the parent to make sure the invalidate request goes // through final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION; - + + // Check whether the child that requests the invalidate is fully opaque + final boolean isOpaque = child.isOpaque(); + // Mark the child as dirty, using the appropriate flag + // Make sure we do not set both flags at the same time + final int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY; + do { + View view = null; + if (parent instanceof View) { + view = (View) parent; + } + if (drawAnimation) { - if (parent instanceof View) { - ((View) parent).mPrivateFlags |= DRAW_ANIMATION; + if (view != null) { + view.mPrivateFlags |= DRAW_ANIMATION; } else if (parent instanceof ViewRoot) { ((ViewRoot) parent).mIsAnimating = true; } } + + // If the parent is dirty opaque or not dirty, mark it dirty with the opaque + // flag coming from the child that initiated the invalidate + if (view != null && (view.mPrivateFlags & DIRTY_MASK) != DIRTY) { + view.mPrivateFlags = (view.mPrivateFlags & ~DIRTY_MASK) | opaqueFlag; + } + parent = parent.invalidateChildInParent(location, dirty); } while (parent != null); } diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 0b03626..819bc31 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -539,6 +539,7 @@ public final class ViewRoot extends Handler implements ViewParent, } dirty = mTempRect; } + // TODO: When doing a union with mDirty != empty, we must cancel all the DIRTY_OPAQUE flags mDirty.union(dirty); if (!mWillDrawSoon) { scheduleTraversals(); diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java index 5f8acc8..17d3f94 100644 --- a/core/java/android/webkit/CallbackProxy.java +++ b/core/java/android/webkit/CallbackProxy.java @@ -98,6 +98,7 @@ class CallbackProxy extends Handler { private static final int SCALE_CHANGED = 123; private static final int RECEIVED_CERTIFICATE = 124; private static final int SWITCH_OUT_HISTORY = 125; + private static final int JS_TIMEOUT = 126; // Message triggered by the client to resume execution private static final int NOTIFY = 200; @@ -530,6 +531,18 @@ class CallbackProxy extends Handler { } break; + case JS_TIMEOUT: + if(mWebChromeClient != null) { + final JsResult res = (JsResult) msg.obj; + if(mWebChromeClient.onJsTimeout()) { + res.confirm(); + } else { + res.cancel(); + } + res.setReady(); + } + break; + case RECEIVED_CERTIFICATE: mWebView.setCertificate((SslCertificate) msg.obj); break; @@ -1022,4 +1035,26 @@ class CallbackProxy extends Handler { } return result.getResult(); } + + /** + * @hide pending API council approval + */ + public boolean onJsTimeout() { + //always interrupt timedout JS by default + if (mWebChromeClient == null) { + return true; + } + JsResult result = new JsResult(this, true); + Message timeout = obtainMessage(JS_TIMEOUT, result); + synchronized (this) { + sendMessage(timeout); + 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/CookieManager.java b/core/java/android/webkit/CookieManager.java index c0c6775..e8c2279 100644 --- a/core/java/android/webkit/CookieManager.java +++ b/core/java/android/webkit/CookieManager.java @@ -647,8 +647,6 @@ public final class CookieManager { // 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 diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index f940006..9d9763c 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -157,4 +157,19 @@ public class WebChromeClient { JsResult result) { return false; } + + /** + * Tell the client that a JavaScript execution timeout has occured. And the + * client may decide whether or not to interrupt the execution. If the + * client returns true, the JavaScript will be interrupted. If the client + * returns false, the execution will continue. Note that in the case of + * continuing execution, the timeout counter will be reset, and the callback + * will continue to occur if the script does not finish at the next check + * point. + * @return boolean Whether the JavaScript execution should be interrupted. + * @hide pending API Council approval + */ + public boolean onJsTimeout() { + return true; + } } diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 58d8ae7..e9df453 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -263,6 +263,16 @@ final class WebViewCore { return mCallbackProxy.onJsBeforeUnload(url, message); } + /** + * + * Callback to notify that a JavaScript execution timeout has occured. + * @return True if the JavaScript execution should be interrupted. False + * will continue the execution. + */ + protected boolean jsInterrupt() { + return mCallbackProxy.onJsTimeout(); + } + //------------------------------------------------------------------------- // JNI methods //------------------------------------------------------------------------- diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 767c7e7..4f503b4 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -433,7 +433,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te private InputConnection mDefInputConnection; private InputConnectionWrapper mPublicInputConnection; - + + private Runnable mClearScrollingCache; + /** * Interface definition for a callback to be invoked when the list or grid * has been scrolled. @@ -2299,6 +2301,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } if (more) { + invalidate(); mLastFlingY = y; post(this); } else { @@ -2322,16 +2325,23 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } private void clearScrollingCache() { - if (mCachingStarted) { - setChildrenDrawnWithCacheEnabled(false); - if ((mPersistentDrawingCache & PERSISTENT_SCROLLING_CACHE) == 0) { - setChildrenDrawingCacheEnabled(false); - } - if (!isAlwaysDrawnWithCacheEnabled()) { - invalidate(); - } - mCachingStarted = false; + if (mClearScrollingCache == null) { + mClearScrollingCache = new Runnable() { + public void run() { + if (mCachingStarted) { + mCachingStarted = false; + setChildrenDrawnWithCacheEnabled(false); + if ((mPersistentDrawingCache & PERSISTENT_SCROLLING_CACHE) == 0) { + setChildrenDrawingCacheEnabled(false); + } + if (!isAlwaysDrawnWithCacheEnabled()) { + invalidate(); + } + } + } + }; } + post(mClearScrollingCache); } /** @@ -2788,7 +2798,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te 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: The 20 below should come from the theme // TODO: And the gravity should be defined in the theme as well final int bottomGap = screenHeight - xy[1] - getHeight() + (int) (mDensityScale * 20); if (!mPopup.isShowing()) { diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index 9c10f0a..a1d16ea 100644 --- a/core/java/android/widget/AutoCompleteTextView.java +++ b/core/java/android/widget/AutoCompleteTextView.java @@ -208,7 +208,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe && mPopup.isShowing() && mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED) { mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); - mPopup.update(); + showDropDown(); } } @@ -1171,9 +1171,14 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe } } - // Max height available on the screen for a popup - final int maxHeight = - mPopup.getMaxAvailableHeight(getDropDownAnchorView(), mDropDownVerticalOffset); + // Max height available on the screen for a popup. If this AutoCompleteTextView has + // the dropDownAlwaysVisible attribute, and the input method is not currently required, + // we then we ask for the height ignoring any bottom decorations like the input method. + // Otherwise we respect the input method. + boolean ignoreBottomDecorations = mDropDownAlwaysVisible && + mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; + final int maxHeight = mPopup.getMaxAvailableHeight( + getDropDownAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations); final int measuredHeight = mDropDownList.measureHeightOfChildren(MeasureSpec.UNSPECIFIED, 0, ListView.NO_POSITION, maxHeight - otherHeights, 2) + otherHeights; @@ -1255,7 +1260,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); - mPopup.update(); + showDropDown(); } return false; } diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java index 66c162e..5472d68 100644 --- a/core/java/android/widget/ListView.java +++ b/core/java/android/widget/ListView.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; +import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.graphics.drawable.ColorDrawable; import android.os.Parcel; @@ -113,7 +114,11 @@ public class ListView extends AbsListView { Drawable mDivider; int mDividerHeight; + + private boolean mIsCacheColorOpaque; + private boolean mDividerIsOpaque; private boolean mClipDivider; + private boolean mHeaderDividersEnabled; private boolean mFooterDividersEnabled; @@ -2776,6 +2781,20 @@ public class ListView extends AbsListView { return mItemsCanFocus; } + /** + * @hide Pending API council approval. + */ + @Override + public boolean isOpaque() { + return (mCachingStarted && mIsCacheColorOpaque && mDividerIsOpaque) || super.isOpaque(); + } + + @Override + public void setCacheColorHint(int color) { + mIsCacheColorOpaque = (color >>> 24) == 0xFF; + super.setCacheColorHint(color); + } + @Override protected void dispatchDraw(Canvas canvas) { // Draw the dividers @@ -2897,6 +2916,7 @@ public class ListView extends AbsListView { mClipDivider = false; } mDivider = divider; + mDividerIsOpaque = divider == null || divider.getOpacity() == PixelFormat.OPAQUE; requestLayoutIfNecessary(); } diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 2c9714e..acd25ee 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -25,6 +25,7 @@ import android.view.WindowManager; import android.view.Gravity; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import android.view.WindowManagerImpl; import android.view.ViewTreeObserver.OnScrollChangedListener; import android.view.View.OnTouchListener; import android.graphics.PixelFormat; @@ -948,14 +949,38 @@ public class PopupWindow { * shown. */ public int getMaxAvailableHeight(View anchor, int yOffset) { + return getMaxAvailableHeight(anchor, yOffset, false); + } + + /** + * Returns the maximum height that is available for the popup to be + * completely shown, optionally ignoring any bottom decorations such as + * the input method. 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 + * @param ignoreBottomDecorations if true, the height returned will be + * all the way to the bottom of the display, ignoring any + * bottom decorations + * @return The maximum available height for the popup to be completely + * shown. + * + * @hide Pending API council approval. + */ + public int getMaxAvailableHeight(View anchor, int yOffset, boolean ignoreBottomDecorations) { 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; + int bottomEdge = displayFrame.bottom; + if (ignoreBottomDecorations) { + bottomEdge = WindowManagerImpl.getDefault().getDefaultDisplay().getHeight(); + } + final int distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset; final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset; // anchorPos[1] is distance from anchor to top of screen @@ -1116,7 +1141,7 @@ public class PopupWindow { p.flags = newFlags; update = true; } - + if (update) { mWindowManager.updateViewLayout(mPopupView, p); } diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java index c4f0abd..edbb3db 100644 --- a/core/java/android/widget/RelativeLayout.java +++ b/core/java/android/widget/RelativeLayout.java @@ -823,7 +823,7 @@ public class RelativeLayout extends ViewGroup { @ViewDebug.IntToString(from = RIGHT_OF, to = "rightOf") }, mapping = { @ViewDebug.IntToString(from = TRUE, to = "true"), - @ViewDebug.IntToString(from = 0, to = "NO_ID") + @ViewDebug.IntToString(from = 0, to = "FALSE/NO_ID") }) private int[] mRules = new int[VERB_COUNT]; diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java new file mode 100644 index 0000000..77d6e20 --- /dev/null +++ b/core/java/com/android/internal/app/ShutdownThread.java @@ -0,0 +1,241 @@ +/* + * 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.app.ActivityManagerNative; +import android.app.IActivityManager; +import android.app.ProgressDialog; +import android.app.AlertDialog; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.IBluetoothDevice; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Handler; +import android.os.RemoteException; +import android.os.Power; +import android.os.ServiceManager; +import android.os.SystemClock; +import com.android.internal.telephony.ITelephony; +import android.util.Log; +import android.view.WindowManager; + +public final class ShutdownThread extends Thread { + // constants + private static final String TAG = "ShutdownThread"; + private static final int MAX_NUM_PHONE_STATE_READS = 16; + private static final int PHONE_STATE_POLL_SLEEP_MSEC = 500; + // maximum time we wait for the shutdown broadcast before going on. + private static final int MAX_BROADCAST_TIME = 10*1000; + + // state tracking + private static Object sIsStartedGuard = new Object(); + private static boolean sIsStarted = false; + + // static instance of this thread + private static final ShutdownThread sInstance = new ShutdownThread(); + + private final Object mBroadcastDoneSync = new Object(); + private boolean mBroadcastDone; + private Context mContext; + private Handler mHandler; + + private ShutdownThread() { + } + + /** + * Request a clean shutdown, waiting for subsystems to clean up their + * state etc. Must be called from a Looper thread in which its UI + * is shown. + * + * @param context Context used to display the shutdown progress dialog. + */ + public static void shutdown(final Context context, boolean confirm) { + // ensure that only one thread is trying to power down. + // any additional calls are just returned + synchronized (sIsStartedGuard){ + if (sIsStarted) { + Log.d(TAG, "Request to shutdown already running, returning."); + return; + } + } + + Log.d(TAG, "Notifying thread to start radio shutdown"); + + if (confirm) { + final AlertDialog dialog = new AlertDialog.Builder(context) + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(com.android.internal.R.string.power_off) + .setMessage(com.android.internal.R.string.shutdown_confirm) + .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + beginShutdownSequence(context); + } + }) + .setNegativeButton(com.android.internal.R.string.no, null) + .create(); + dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND); + dialog.show(); + } else { + beginShutdownSequence(context); + } + } + + private static void beginShutdownSequence(Context context) { + synchronized (sIsStartedGuard) { + sIsStarted = true; + } + + // throw up an indeterminate system dialog to indicate radio is + // shutting down. + ProgressDialog pd = new ProgressDialog(context); + pd.setTitle(context.getText(com.android.internal.R.string.power_off)); + pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); + pd.setIndeterminate(true); + pd.setCancelable(false); + pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); + pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND); + + pd.show(); + + // start the thread that initiates shutdown + sInstance.mContext = context; + sInstance.mHandler = new Handler() { + }; + sInstance.start(); + } + + void broadcastDone() { + synchronized (mBroadcastDoneSync) { + mBroadcastDone = true; + mBroadcastDoneSync.notifyAll(); + } + } + + /** + * Makes sure we handle the shutdown gracefully. + * Shuts off power regardless of radio and bluetooth state if the alloted time has passed. + */ + public void run() { + boolean bluetoothOff; + boolean radioOff; + + BroadcastReceiver br = new BroadcastReceiver() { + @Override public void onReceive(Context context, Intent intent) { + // We don't allow apps to cancel this, so ignore the result. + broadcastDone(); + } + }; + + Log.i(TAG, "Sending shutdown broadcast..."); + + // First send the high-level shut down broadcast. + mBroadcastDone = false; + mContext.sendOrderedBroadcast(new Intent(Intent.ACTION_SHUTDOWN), null, + br, mHandler, 0, null, null); + + final long endTime = System.currentTimeMillis() + MAX_BROADCAST_TIME; + synchronized (mBroadcastDoneSync) { + while (!mBroadcastDone) { + long delay = endTime - System.currentTimeMillis(); + if (delay <= 0) { + Log.w(TAG, "Shutdown broadcast timed out"); + break; + } + try { + mBroadcastDoneSync.wait(delay); + } catch (InterruptedException e) { + } + } + } + + Log.i(TAG, "Shutting down activity manager..."); + + final IActivityManager am = + ActivityManagerNative.asInterface(ServiceManager.checkService("activity")); + if (am != null) { + try { + am.shutdown(MAX_BROADCAST_TIME); + } catch (RemoteException e) { + } + } + + final ITelephony phone = + ITelephony.Stub.asInterface(ServiceManager.checkService("phone")); + final IBluetoothDevice bluetooth = + IBluetoothDevice.Stub.asInterface(ServiceManager.checkService( + Context.BLUETOOTH_SERVICE)); + + try { + bluetoothOff = bluetooth == null || + bluetooth.getBluetoothState() == BluetoothDevice.BLUETOOTH_STATE_OFF; + if (!bluetoothOff) { + Log.w(TAG, "Disabling Bluetooth..."); + bluetooth.disable(false); // disable but don't persist new state + } + } catch (RemoteException ex) { + Log.e(TAG, "RemoteException during bluetooth shutdown", ex); + bluetoothOff = true; + } + + try { + radioOff = phone == null || !phone.isRadioOn(); + if (!radioOff) { + Log.w(TAG, "Turning off radio..."); + phone.setRadio(false); + } + } catch (RemoteException ex) { + Log.e(TAG, "RemoteException during radio shutdown", ex); + radioOff = true; + } + + Log.i(TAG, "Waiting for Bluetooth and Radio..."); + + // Wait a max of 32 seconds for clean shutdown + for (int i = 0; i < MAX_NUM_PHONE_STATE_READS; i++) { + if (!bluetoothOff) { + try { + bluetoothOff = + bluetooth.getBluetoothState() == BluetoothDevice.BLUETOOTH_STATE_OFF; + } catch (RemoteException ex) { + Log.e(TAG, "RemoteException during bluetooth shutdown", ex); + bluetoothOff = true; + } + } + if (!radioOff) { + try { + radioOff = !phone.isRadioOn(); + } catch (RemoteException ex) { + Log.e(TAG, "RemoteException during radio shutdown", ex); + radioOff = true; + } + } + if (radioOff && bluetoothOff) { + Log.i(TAG, "Radio and Bluetooth shutdown complete."); + break; + } + SystemClock.sleep(PHONE_STATE_POLL_SLEEP_MSEC); + } + + //shutdown power + Log.i(TAG, "Performing low-level shutdown..."); + Power.shutdown(); + } +} diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl index d64a303..ce39768 100644 --- a/core/java/com/android/internal/backup/IBackupTransport.aidl +++ b/core/java/com/android/internal/backup/IBackupTransport.aidl @@ -16,6 +16,54 @@ package com.android.internal.backup; +import android.os.ParcelFileDescriptor; + /** {@hide} */ interface IBackupTransport { +/* STOPSHIP - don't ship with this comment in place + Things the transport interface has to do: + 1. set up the connection to the destination + - set up encryption + - for Google cloud, log in using the user's gaia credential or whatever + - for sd, spin off the backup transport and establish communication with it + 2. send each app's backup transaction + - parse the data file for key/value pointers etc + - send key/blobsize set to the Google cloud, get back quota ok/rejected response + - sd/adb doesn't preflight; no per-app quota + - app's entire change is essentially atomic + - cloud transaction encrypts then sends each key/value pair separately; we already + parsed the data when preflighting so we don't have to again here + - sd target streams raw data into encryption envelope then to sd? + 3. shut down connection to destination + - cloud: tear down connection etc + - sd: close the file and shut down the writer proxy +*/ + /** + * Establish a connection to the back-end data repository, if necessary. If the transport + * needs to initialize state that is not tied to individual applications' backup operations, + * this is where it should be done. + * + * @return Zero on success; a nonzero error code on failure. + */ + int startSession(); + + /** + * Send one application's data to the backup destination. + * + * @param packageName The identity of the application whose data is being backed up. + * @param data The data stream that resulted from invoking the application's + * BackupService.doBackup() method. This may be a pipe rather than a + * file on persistent media, so it may not be seekable. + * @return Zero on success; a nonzero error code on failure. + */ + int performBackup(String packageName, in ParcelFileDescriptor data); + + /** + * Terminate the backup session, closing files, freeing memory, and cleaning up whatever + * other state the transport required. + * + * @return Zero on success; a nonzero error code on failure. Even on failure, the session + * is torn down and must be restarted if another backup is attempted. + */ + int endSession(); } diff --git a/core/jni/Android.mk b/core/jni/Android.mk index ac35459..4839b6f 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -116,7 +116,8 @@ LOCAL_SRC_FILES:= \ android_ddm_DdmHandleNativeHeap.cpp \ android_location_GpsLocationProvider.cpp \ com_android_internal_os_ZygoteInit.cpp \ - com_android_internal_graphics_NativeUtils.cpp + com_android_internal_graphics_NativeUtils.cpp \ + android_backup_FileBackupHelper.cpp LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 7c9f457..aa6450d 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -155,6 +155,7 @@ extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env); extern int register_com_android_internal_os_ZygoteInit(JNIEnv* env); extern int register_android_util_Base64(JNIEnv* env); extern int register_android_location_GpsLocationProvider(JNIEnv* env); +extern int register_android_backup_FileBackupHelper(JNIEnv *env); static AndroidRuntime* gCurRuntime = NULL; @@ -1125,6 +1126,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_ddm_DdmHandleNativeHeap), REG_JNI(register_android_util_Base64), REG_JNI(register_android_location_GpsLocationProvider), + REG_JNI(register_android_backup_FileBackupHelper), }; /* diff --git a/core/jni/android_backup_FileBackupHelper.cpp b/core/jni/android_backup_FileBackupHelper.cpp new file mode 100644 index 0000000..e8d60a0 --- /dev/null +++ b/core/jni/android_backup_FileBackupHelper.cpp @@ -0,0 +1,79 @@ +/* + * 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. + */ + +#include "JNIHelp.h" +#include <android_runtime/AndroidRuntime.h> + +#include <utils/backup_helpers.h> + +namespace android +{ + +static jfieldID s_descriptorField; + +static int +performBackup_native(JNIEnv* env, jstring basePath, + jobject oldSnapshot, jobject newSnapshot, + jobject data, jobjectArray files) +{ + int err; + + // all parameters have already been checked against null + + int oldSnapshotFD = env->GetIntField(oldSnapshot, s_descriptorField); + int newSnapshotFD = env->GetIntField(newSnapshot, s_descriptorField); + int dataFD = env->GetIntField(data, s_descriptorField); + + char const* basePathUTF = env->GetStringUTFChars(basePath, NULL); + const int fileCount = env->GetArrayLength(files); + char const** filesUTF = (char const**)malloc(sizeof(char*)*fileCount); + for (int i=0; i<fileCount; i++) { + filesUTF[i] = env->GetStringUTFChars((jstring)env->GetObjectArrayElement(files, i), NULL); + } + + err = back_up_files(oldSnapshotFD, newSnapshotFD, dataFD, basePathUTF, filesUTF, fileCount); + + for (int i=0; i<fileCount; i++) { + env->ReleaseStringUTFChars((jstring)env->GetObjectArrayElement(files, i), filesUTF[i]); + } + free(filesUTF); + env->ReleaseStringUTFChars(basePath, basePathUTF); + + return err; +} + +static const JNINativeMethod g_methods[] = { + { "performBackup_native", + "(Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;" + "Ljava/io/FileDescriptor;[Ljava/lang/String;)I", + (void*)performBackup_native }, +}; + +int register_android_backup_FileBackupHelper(JNIEnv* env) +{ + jclass clazz; + + clazz = env->FindClass("java/io/FileDescriptor"); + LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor"); + s_descriptorField = env->GetFieldID(clazz, "descriptor", "I"); + LOG_FATAL_IF(s_descriptorField == NULL, + "Unable to find descriptor field in java.io.FileDescriptor"); + + return AndroidRuntime::registerNativeMethods(env, "android/backup/FileBackupHelper", + g_methods, NELEM(g_methods)); +} + +} diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp index 9c63fd2..004b0e3 100644 --- a/core/jni/android_location_GpsLocationProvider.cpp +++ b/core/jni/android_location_GpsLocationProvider.cpp @@ -31,31 +31,31 @@ static pthread_cond_t sEventCond = PTHREAD_COND_INITIALIZER; static jmethodID method_reportLocation; static jmethodID method_reportStatus; static jmethodID method_reportSvStatus; -static jmethodID method_reportSuplStatus; +static jmethodID method_reportAGpsStatus; static jmethodID method_xtraDownloadRequest; static const GpsInterface* sGpsInterface = NULL; static const GpsXtraInterface* sGpsXtraInterface = NULL; -static const GpsSuplInterface* sGpsSuplInterface = NULL; +static const AGpsInterface* sAGpsInterface = NULL; // data written to by GPS callbacks static GpsLocation sGpsLocation; static GpsStatus sGpsStatus; static GpsSvStatus sGpsSvStatus; -static GpsSuplStatus sGpsSuplStatus; +static AGpsStatus sAGpsStatus; // a copy of the data shared by android_location_GpsLocationProvider_wait_for_event // and android_location_GpsLocationProvider_read_status static GpsLocation sGpsLocationCopy; static GpsStatus sGpsStatusCopy; static GpsSvStatus sGpsSvStatusCopy; -static GpsSuplStatus sGpsSuplStatusCopy; +static AGpsStatus sAGpsStatusCopy; enum CallbackType { kLocation = 1, kStatus = 2, kSvStatus = 4, - kSuplStatus = 8, + kAGpsStatus = 8, kXtraDownloadRequest = 16, kDisableRequest = 32, }; @@ -96,12 +96,12 @@ static void sv_status_callback(GpsSvStatus* sv_status) pthread_mutex_unlock(&sEventMutex); } -static void supl_status_callback(GpsSuplStatus* supl_status) +static void agps_status_callback(AGpsStatus* agps_status) { pthread_mutex_lock(&sEventMutex); - sPendingCallbacks |= kSuplStatus; - memcpy(&sGpsSuplStatus, supl_status, sizeof(GpsSuplStatus)); + sPendingCallbacks |= kAGpsStatus; + memcpy(&sAGpsStatus, agps_status, sizeof(AGpsStatus)); pthread_cond_signal(&sEventCond); pthread_mutex_unlock(&sEventMutex); @@ -126,15 +126,15 @@ GpsXtraCallbacks sGpsXtraCallbacks = { download_request_callback, }; -GpsSuplCallbacks sGpsSuplCallbacks = { - supl_status_callback, +AGpsCallbacks sAGpsCallbacks = { + agps_status_callback, }; static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) { method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V"); method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V"); method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V"); - method_reportSuplStatus = env->GetMethodID(clazz, "reportSuplStatus", "(I)V"); + method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II)V"); method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V"); } @@ -151,10 +151,10 @@ static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject o if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0) return false; - if (!sGpsSuplInterface) - sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); - if (sGpsSuplInterface) - sGpsSuplInterface->init(&sGpsSuplCallbacks); + if (!sAGpsInterface) + sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE); + if (sAGpsInterface) + sAGpsInterface->init(&sAGpsCallbacks); return true; } @@ -187,12 +187,6 @@ static jboolean android_location_GpsLocationProvider_stop(JNIEnv* env, jobject o return (sGpsInterface->stop() == 0); } -static void android_location_GpsLocationProvider_set_fix_frequency(JNIEnv* env, jobject obj, jint fixFrequency) -{ - if (sGpsInterface->set_fix_frequency) - sGpsInterface->set_fix_frequency(fixFrequency); -} - static void android_location_GpsLocationProvider_delete_aiding_data(JNIEnv* env, jobject obj, jint flags) { sGpsInterface->delete_aiding_data(flags); @@ -212,7 +206,7 @@ static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, job memcpy(&sGpsLocationCopy, &sGpsLocation, sizeof(sGpsLocationCopy)); memcpy(&sGpsStatusCopy, &sGpsStatus, sizeof(sGpsStatusCopy)); memcpy(&sGpsSvStatusCopy, &sGpsSvStatus, sizeof(sGpsSvStatusCopy)); - memcpy(&sGpsSuplStatusCopy, &sGpsSuplStatus, sizeof(sGpsSuplStatusCopy)); + memcpy(&sAGpsStatusCopy, &sAGpsStatus, sizeof(sAGpsStatusCopy)); pthread_mutex_unlock(&sEventMutex); if (pendingCallbacks & kLocation) { @@ -228,8 +222,8 @@ static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, job if (pendingCallbacks & kSvStatus) { env->CallVoidMethod(obj, method_reportSvStatus); } - if (pendingCallbacks & kSuplStatus) { - env->CallVoidMethod(obj, method_reportSuplStatus, sGpsSuplStatusCopy.status); + if (pendingCallbacks & kAGpsStatus) { + env->CallVoidMethod(obj, method_reportAGpsStatus, sAGpsStatusCopy.type, sAGpsStatusCopy.status); } if (pendingCallbacks & kXtraDownloadRequest) { env->CallVoidMethod(obj, method_xtraDownloadRequest); @@ -299,73 +293,72 @@ static void android_location_GpsLocationProvider_inject_xtra_data(JNIEnv* env, j env->ReleaseByteArrayElements(data, bytes, 0); } -static void android_location_GpsLocationProvider_supl_data_conn_open(JNIEnv* env, jobject obj, jstring apn) +static void android_location_GpsLocationProvider_agps_data_conn_open(JNIEnv* env, jobject obj, jstring apn) { - if (!sGpsSuplInterface) { - sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); + if (!sAGpsInterface) { + sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE); } - if (sGpsSuplInterface) { + if (sAGpsInterface) { if (apn == NULL) { jniThrowException(env, "java/lang/IllegalArgumentException", NULL); return; } const char *apnStr = env->GetStringUTFChars(apn, NULL); - sGpsSuplInterface->data_conn_open(apnStr); + sAGpsInterface->data_conn_open(apnStr); env->ReleaseStringUTFChars(apn, apnStr); } } -static void android_location_GpsLocationProvider_supl_data_conn_closed(JNIEnv* env, jobject obj) +static void android_location_GpsLocationProvider_agps_data_conn_closed(JNIEnv* env, jobject obj) { - if (!sGpsSuplInterface) { - sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); + if (!sAGpsInterface) { + sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE); } - if (sGpsSuplInterface) { - sGpsSuplInterface->data_conn_closed(); + if (sAGpsInterface) { + sAGpsInterface->data_conn_closed(); } } -static void android_location_GpsLocationProvider_supl_data_conn_failed(JNIEnv* env, jobject obj) +static void android_location_GpsLocationProvider_agps_data_conn_failed(JNIEnv* env, jobject obj) { - if (!sGpsSuplInterface) { - sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); + if (!sAGpsInterface) { + sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE); } - if (sGpsSuplInterface) { - sGpsSuplInterface->data_conn_failed(); + if (sAGpsInterface) { + sAGpsInterface->data_conn_failed(); } } -static void android_location_GpsLocationProvider_set_supl_server(JNIEnv* env, jobject obj, - jint addr, jint port) +static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jobject obj, + jint type, jint addr, jint port) { - if (!sGpsSuplInterface) { - sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE); + if (!sAGpsInterface) { + sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE); } - if (sGpsSuplInterface) { - sGpsSuplInterface->set_server(addr, port); + if (sAGpsInterface) { + sAGpsInterface->set_server(type, addr, port); } } static JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native}, - {"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported}, - {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init}, - {"native_disable", "()V", (void*)android_location_GpsLocationProvider_disable}, - {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup}, - {"native_start", "(IZI)Z", (void*)android_location_GpsLocationProvider_start}, - {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop}, - {"native_set_fix_frequency", "(I)V", (void*)android_location_GpsLocationProvider_set_fix_frequency}, - {"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data}, - {"native_wait_for_event", "()V", (void*)android_location_GpsLocationProvider_wait_for_event}, - {"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status}, - {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time}, - {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra}, - {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data}, - {"native_supl_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_supl_data_conn_open}, - {"native_supl_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_supl_data_conn_closed}, - {"native_supl_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_supl_data_conn_failed}, - {"native_set_supl_server", "(II)V", (void*)android_location_GpsLocationProvider_set_supl_server}, + {"native_is_supported", "()Z", (void*)android_location_GpsLocationProvider_is_supported}, + {"native_init", "()Z", (void*)android_location_GpsLocationProvider_init}, + {"native_disable", "()V", (void*)android_location_GpsLocationProvider_disable}, + {"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup}, + {"native_start", "(IZI)Z", (void*)android_location_GpsLocationProvider_start}, + {"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop}, + {"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data}, + {"native_wait_for_event", "()V", (void*)android_location_GpsLocationProvider_wait_for_event}, + {"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status}, + {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time}, + {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra}, + {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data}, + {"native_agps_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open}, + {"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed}, + {"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed}, + {"native_set_agps_server", "(III)V", (void*)android_location_GpsLocationProvider_set_agps_server}, }; int register_android_location_GpsLocationProvider(JNIEnv* env) diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp index bc644d2..482d8eb 100644 --- a/core/jni/android_opengl_GLES10.cpp +++ b/core/jni/android_opengl_GLES10.cpp @@ -22,11 +22,20 @@ #include <assert.h> #include <GLES/gl.h> +#include <GLES/glext.h> -#include <private/opengles/gl_context.h> - -#define _NUM_COMPRESSED_TEXTURE_FORMATS \ - (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS) +/* special calls implemented in Android's GLES wrapper used to more + * efficiently bound-check passed arrays */ +extern "C" { +GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr, GLsizei count); +GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride, + const GLvoid *pointer, GLsizei count); +GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer, GLsizei count); +GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer, GLsizei count); +} static int initialized = 0; @@ -67,7 +76,6 @@ nativeClassInitBuffer(JNIEnv *_env) _env->GetFieldID(bufferClass, "_elementSizeShift", "I"); } - static void nativeClassInit(JNIEnv *_env, jclass glImplClass) { @@ -118,7 +126,6 @@ getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining) return (void *) ((char *) data + offset); } - static void releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) { @@ -126,6 +133,13 @@ releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) commit ? 0 : JNI_ABORT); } +static int +getNumCompressedTextureFormats() { + int numCompressedTextureFormats = 0; + glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numCompressedTextureFormats); + return numCompressedTextureFormats; +} + // -------------------------------------------------------------------------- /* void glActiveTexture ( GLenum texture ) */ @@ -290,7 +304,13 @@ android_glColorPointerBounds__IIILjava_nio_Buffer_2I jint _remaining; GLvoid *pointer = (GLvoid *) 0; - pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining); + if (pointer_buf) { + pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + if ( ! pointer ) { + _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); + return; + } + } glColorPointerBounds( (GLint)size, (GLenum)type, @@ -298,9 +318,6 @@ android_glColorPointerBounds__IIILjava_nio_Buffer_2I (GLvoid *)pointer, (GLsizei)remaining ); - if (_array) { - releasePointer(_env, _array, pointer, JNI_FALSE); - } } /* void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data ) */ @@ -1022,6 +1039,12 @@ android_glGetIntegerv__I_3II #if defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES) case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: #endif // defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES) +#if defined(GL_LIGHT_MODEL_COLOR_CONTROL) + case GL_LIGHT_MODEL_COLOR_CONTROL: +#endif // defined(GL_LIGHT_MODEL_COLOR_CONTROL) +#if defined(GL_LIGHT_MODEL_LOCAL_VIEWER) + case GL_LIGHT_MODEL_LOCAL_VIEWER: +#endif // defined(GL_LIGHT_MODEL_LOCAL_VIEWER) #if defined(GL_LIGHT_MODEL_TWO_SIDE) case GL_LIGHT_MODEL_TWO_SIDE: #endif // defined(GL_LIGHT_MODEL_TWO_SIDE) @@ -1236,6 +1259,12 @@ android_glGetIntegerv__I_3II #if defined(GL_COLOR_WRITEMASK) case GL_COLOR_WRITEMASK: #endif // defined(GL_COLOR_WRITEMASK) +#if defined(GL_FOG_COLOR) + case GL_FOG_COLOR: +#endif // defined(GL_FOG_COLOR) +#if defined(GL_LIGHT_MODEL_AMBIENT) + case GL_LIGHT_MODEL_AMBIENT: +#endif // defined(GL_LIGHT_MODEL_AMBIENT) #if defined(GL_SCISSOR_BOX) case GL_SCISSOR_BOX: #endif // defined(GL_SCISSOR_BOX) @@ -1267,13 +1296,7 @@ android_glGetIntegerv__I_3II #if defined(GL_COMPRESSED_TEXTURE_FORMATS) case GL_COMPRESSED_TEXTURE_FORMATS: #endif // defined(GL_COMPRESSED_TEXTURE_FORMATS) -#if defined(GL_FOG_COLOR) - case GL_FOG_COLOR: -#endif // defined(GL_FOG_COLOR) -#if defined(GL_LIGHT_MODEL_AMBIENT) - case GL_LIGHT_MODEL_AMBIENT: -#endif // defined(GL_LIGHT_MODEL_AMBIENT) - _needed = _NUM_COMPRESSED_TEXTURE_FORMATS; + _needed = getNumCompressedTextureFormats(); break; default: _needed = 0; @@ -1378,6 +1401,12 @@ android_glGetIntegerv__ILjava_nio_IntBuffer_2 #if defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES) case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: #endif // defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES) +#if defined(GL_LIGHT_MODEL_COLOR_CONTROL) + case GL_LIGHT_MODEL_COLOR_CONTROL: +#endif // defined(GL_LIGHT_MODEL_COLOR_CONTROL) +#if defined(GL_LIGHT_MODEL_LOCAL_VIEWER) + case GL_LIGHT_MODEL_LOCAL_VIEWER: +#endif // defined(GL_LIGHT_MODEL_LOCAL_VIEWER) #if defined(GL_LIGHT_MODEL_TWO_SIDE) case GL_LIGHT_MODEL_TWO_SIDE: #endif // defined(GL_LIGHT_MODEL_TWO_SIDE) @@ -1592,6 +1621,12 @@ android_glGetIntegerv__ILjava_nio_IntBuffer_2 #if defined(GL_COLOR_WRITEMASK) case GL_COLOR_WRITEMASK: #endif // defined(GL_COLOR_WRITEMASK) +#if defined(GL_FOG_COLOR) + case GL_FOG_COLOR: +#endif // defined(GL_FOG_COLOR) +#if defined(GL_LIGHT_MODEL_AMBIENT) + case GL_LIGHT_MODEL_AMBIENT: +#endif // defined(GL_LIGHT_MODEL_AMBIENT) #if defined(GL_SCISSOR_BOX) case GL_SCISSOR_BOX: #endif // defined(GL_SCISSOR_BOX) @@ -1623,13 +1658,7 @@ android_glGetIntegerv__ILjava_nio_IntBuffer_2 #if defined(GL_COMPRESSED_TEXTURE_FORMATS) case GL_COMPRESSED_TEXTURE_FORMATS: #endif // defined(GL_COMPRESSED_TEXTURE_FORMATS) -#if defined(GL_FOG_COLOR) - case GL_FOG_COLOR: -#endif // defined(GL_FOG_COLOR) -#if defined(GL_LIGHT_MODEL_AMBIENT) - case GL_LIGHT_MODEL_AMBIENT: -#endif // defined(GL_LIGHT_MODEL_AMBIENT) - _needed = _NUM_COMPRESSED_TEXTURE_FORMATS; + _needed = getNumCompressedTextureFormats(); break; default: _needed = 0; @@ -2749,16 +2778,19 @@ android_glNormalPointerBounds__IILjava_nio_Buffer_2I jint _remaining; GLvoid *pointer = (GLvoid *) 0; - pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining); + if (pointer_buf) { + pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + if ( ! pointer ) { + _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); + return; + } + } glNormalPointerBounds( (GLenum)type, (GLsizei)stride, (GLvoid *)pointer, (GLsizei)remaining ); - if (_array) { - releasePointer(_env, _array, pointer, JNI_FALSE); - } } /* void glOrthof ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */ @@ -3001,7 +3033,13 @@ android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I jint _remaining; GLvoid *pointer = (GLvoid *) 0; - pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining); + if (pointer_buf) { + pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + if ( ! pointer ) { + _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); + return; + } + } glTexCoordPointerBounds( (GLint)size, (GLenum)type, @@ -3009,9 +3047,6 @@ android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I (GLvoid *)pointer, (GLsizei)remaining ); - if (_array) { - releasePointer(_env, _array, pointer, JNI_FALSE); - } } /* void glTexEnvf ( GLenum target, GLenum pname, GLfloat param ) */ @@ -3356,7 +3391,13 @@ android_glVertexPointerBounds__IIILjava_nio_Buffer_2I jint _remaining; GLvoid *pointer = (GLvoid *) 0; - pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining); + if (pointer_buf) { + pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + if ( ! pointer ) { + _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); + return; + } + } glVertexPointerBounds( (GLint)size, (GLenum)type, @@ -3364,9 +3405,6 @@ android_glVertexPointerBounds__IIILjava_nio_Buffer_2I (GLvoid *)pointer, (GLsizei)remaining ); - if (_array) { - releasePointer(_env, _array, pointer, JNI_FALSE); - } } /* void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height ) */ diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp index 6114d6a..f17ef21 100644 --- a/core/jni/android_opengl_GLES10Ext.cpp +++ b/core/jni/android_opengl_GLES10Ext.cpp @@ -22,11 +22,7 @@ #include <assert.h> #include <GLES/gl.h> - -#include <private/opengles/gl_context.h> - -#define _NUM_COMPRESSED_TEXTURE_FORMATS \ - (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS) +#include <GLES/glext.h> static int initialized = 0; diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp index a7e59a8..ed8dfc8 100644 --- a/core/jni/android_opengl_GLES11.cpp +++ b/core/jni/android_opengl_GLES11.cpp @@ -22,11 +22,7 @@ #include <assert.h> #include <GLES/gl.h> - -#include <private/opengles/gl_context.h> - -#define _NUM_COMPRESSED_TEXTURE_FORMATS \ - (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS) +#include <GLES/glext.h> static int initialized = 0; diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp index 069cec1..6f3495c 100644 --- a/core/jni/android_opengl_GLES11Ext.cpp +++ b/core/jni/android_opengl_GLES11Ext.cpp @@ -22,11 +22,7 @@ #include <assert.h> #include <GLES/gl.h> - -#include <private/opengles/gl_context.h> - -#define _NUM_COMPRESSED_TEXTURE_FORMATS \ - (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS) +#include <GLES/glext.h> static int initialized = 0; diff --git a/core/jni/android_os_ParcelFileDescriptor.cpp b/core/jni/android_os_ParcelFileDescriptor.cpp index 971f87c..848a57a 100644 --- a/core/jni/android_os_ParcelFileDescriptor.cpp +++ b/core/jni/android_os_ParcelFileDescriptor.cpp @@ -1,19 +1,18 @@ -/* //device/libs/android_runtime/android_os_ParcelFileDescriptor.cpp -** -** 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. -*/ +/* + * 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. + */ //#define LOG_NDEBUG 0 diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp index b320c09..fe94642 100644 --- a/core/jni/android_server_BluetoothA2dpService.cpp +++ b/core/jni/android_server_BluetoothA2dpService.cpp @@ -45,7 +45,8 @@ static jmethodID method_onSinkPlaying; static jmethodID method_onSinkStopped; typedef struct { - JNIEnv *env; + JavaVM *vm; + int envVer; DBusConnection *conn; jobject me; // for callbacks to java } native_data_t; @@ -70,7 +71,8 @@ static bool initNative(JNIEnv* env, jobject object) { LOGE("%s: out of memory!", __FUNCTION__); return false; } - nat->env = env; + env->GetJavaVM( &(nat->vm) ); + nat->envVer = env->GetVersion(); nat->me = env->NewGlobalRef(object); DBusError err; @@ -239,8 +241,14 @@ static void onConnectSinkResult(DBusMessage *msg, void *user, void *natData) { char *c_path = (char *)user; DBusError err; + JNIEnv *env; + + if (nat->vm->GetEnv((void**)&env, nat->envVer) < 0) { + LOGE("%s: error finding Env for our VM\n", __FUNCTION__); + return; + } + dbus_error_init(&err); - JNIEnv *env = nat->env; LOGV("... path = %s", c_path); if (dbus_set_error_from_message(&err, msg)) { @@ -264,8 +272,14 @@ static void onDisconnectSinkResult(DBusMessage *msg, void *user, void *natData) char *c_path = (char *)user; DBusError err; + JNIEnv *env; + + if (nat->vm->GetEnv((void**)&env, nat->envVer) < 0) { + LOGE("%s: error finding Env for our VM\n", __FUNCTION__); + return; + } + dbus_error_init(&err); - JNIEnv *env = nat->env; LOGV("... path = %s", c_path); if (dbus_set_error_from_message(&err, msg)) { diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp index 4ca79b5..11822e0 100644 --- a/core/jni/com_google_android_gles_jni_GLImpl.cpp +++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp @@ -22,11 +22,20 @@ #include <assert.h> #include <GLES/gl.h> +#include <GLES/glext.h> -#include <private/opengles/gl_context.h> - -#define _NUM_COMPRESSED_TEXTURE_FORMATS \ - (::android::OGLES_NUM_COMPRESSED_TEXTURE_FORMATS) +/* special calls implemented in Android's GLES wrapper used to more + * efficiently bound-check passed arrays */ +extern "C" { +GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride, + const GLvoid *ptr, GLsizei count); +GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride, + const GLvoid *pointer, GLsizei count); +GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer, GLsizei count); +GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type, + GLsizei stride, const GLvoid *pointer, GLsizei count); +} static int initialized = 0; @@ -67,7 +76,6 @@ nativeClassInitBuffer(JNIEnv *_env) _env->GetFieldID(bufferClass, "_elementSizeShift", "I"); } - static void nativeClassInit(JNIEnv *_env, jclass glImplClass) { @@ -118,7 +126,6 @@ getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining) return (void *) ((char *) data + offset); } - static void releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) { @@ -126,6 +133,13 @@ releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit) commit ? 0 : JNI_ABORT); } +static int +getNumCompressedTextureFormats() { + int numCompressedTextureFormats = 0; + glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numCompressedTextureFormats); + return numCompressedTextureFormats; +} + // -------------------------------------------------------------------------- /* void glActiveTexture ( GLenum texture ) */ @@ -290,7 +304,13 @@ android_glColorPointerBounds__IIILjava_nio_Buffer_2I jint _remaining; GLvoid *pointer = (GLvoid *) 0; - pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining); + if (pointer_buf) { + pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + if ( ! pointer ) { + _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); + return; + } + } glColorPointerBounds( (GLint)size, (GLenum)type, @@ -298,9 +318,6 @@ android_glColorPointerBounds__IIILjava_nio_Buffer_2I (GLvoid *)pointer, (GLsizei)remaining ); - if (_array) { - releasePointer(_env, _array, pointer, JNI_FALSE); - } } /* void glCompressedTexImage2D ( GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data ) */ @@ -1022,6 +1039,12 @@ android_glGetIntegerv__I_3II #if defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES) case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: #endif // defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES) +#if defined(GL_LIGHT_MODEL_COLOR_CONTROL) + case GL_LIGHT_MODEL_COLOR_CONTROL: +#endif // defined(GL_LIGHT_MODEL_COLOR_CONTROL) +#if defined(GL_LIGHT_MODEL_LOCAL_VIEWER) + case GL_LIGHT_MODEL_LOCAL_VIEWER: +#endif // defined(GL_LIGHT_MODEL_LOCAL_VIEWER) #if defined(GL_LIGHT_MODEL_TWO_SIDE) case GL_LIGHT_MODEL_TWO_SIDE: #endif // defined(GL_LIGHT_MODEL_TWO_SIDE) @@ -1236,6 +1259,12 @@ android_glGetIntegerv__I_3II #if defined(GL_COLOR_WRITEMASK) case GL_COLOR_WRITEMASK: #endif // defined(GL_COLOR_WRITEMASK) +#if defined(GL_FOG_COLOR) + case GL_FOG_COLOR: +#endif // defined(GL_FOG_COLOR) +#if defined(GL_LIGHT_MODEL_AMBIENT) + case GL_LIGHT_MODEL_AMBIENT: +#endif // defined(GL_LIGHT_MODEL_AMBIENT) #if defined(GL_SCISSOR_BOX) case GL_SCISSOR_BOX: #endif // defined(GL_SCISSOR_BOX) @@ -1267,13 +1296,7 @@ android_glGetIntegerv__I_3II #if defined(GL_COMPRESSED_TEXTURE_FORMATS) case GL_COMPRESSED_TEXTURE_FORMATS: #endif // defined(GL_COMPRESSED_TEXTURE_FORMATS) -#if defined(GL_FOG_COLOR) - case GL_FOG_COLOR: -#endif // defined(GL_FOG_COLOR) -#if defined(GL_LIGHT_MODEL_AMBIENT) - case GL_LIGHT_MODEL_AMBIENT: -#endif // defined(GL_LIGHT_MODEL_AMBIENT) - _needed = _NUM_COMPRESSED_TEXTURE_FORMATS; + _needed = getNumCompressedTextureFormats(); break; default: _needed = 0; @@ -1378,6 +1401,12 @@ android_glGetIntegerv__ILjava_nio_IntBuffer_2 #if defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES) case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: #endif // defined(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES) +#if defined(GL_LIGHT_MODEL_COLOR_CONTROL) + case GL_LIGHT_MODEL_COLOR_CONTROL: +#endif // defined(GL_LIGHT_MODEL_COLOR_CONTROL) +#if defined(GL_LIGHT_MODEL_LOCAL_VIEWER) + case GL_LIGHT_MODEL_LOCAL_VIEWER: +#endif // defined(GL_LIGHT_MODEL_LOCAL_VIEWER) #if defined(GL_LIGHT_MODEL_TWO_SIDE) case GL_LIGHT_MODEL_TWO_SIDE: #endif // defined(GL_LIGHT_MODEL_TWO_SIDE) @@ -1592,6 +1621,12 @@ android_glGetIntegerv__ILjava_nio_IntBuffer_2 #if defined(GL_COLOR_WRITEMASK) case GL_COLOR_WRITEMASK: #endif // defined(GL_COLOR_WRITEMASK) +#if defined(GL_FOG_COLOR) + case GL_FOG_COLOR: +#endif // defined(GL_FOG_COLOR) +#if defined(GL_LIGHT_MODEL_AMBIENT) + case GL_LIGHT_MODEL_AMBIENT: +#endif // defined(GL_LIGHT_MODEL_AMBIENT) #if defined(GL_SCISSOR_BOX) case GL_SCISSOR_BOX: #endif // defined(GL_SCISSOR_BOX) @@ -1623,13 +1658,7 @@ android_glGetIntegerv__ILjava_nio_IntBuffer_2 #if defined(GL_COMPRESSED_TEXTURE_FORMATS) case GL_COMPRESSED_TEXTURE_FORMATS: #endif // defined(GL_COMPRESSED_TEXTURE_FORMATS) -#if defined(GL_FOG_COLOR) - case GL_FOG_COLOR: -#endif // defined(GL_FOG_COLOR) -#if defined(GL_LIGHT_MODEL_AMBIENT) - case GL_LIGHT_MODEL_AMBIENT: -#endif // defined(GL_LIGHT_MODEL_AMBIENT) - _needed = _NUM_COMPRESSED_TEXTURE_FORMATS; + _needed = getNumCompressedTextureFormats(); break; default: _needed = 0; @@ -2749,16 +2778,19 @@ android_glNormalPointerBounds__IILjava_nio_Buffer_2I jint _remaining; GLvoid *pointer = (GLvoid *) 0; - pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining); + if (pointer_buf) { + pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + if ( ! pointer ) { + _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); + return; + } + } glNormalPointerBounds( (GLenum)type, (GLsizei)stride, (GLvoid *)pointer, (GLsizei)remaining ); - if (_array) { - releasePointer(_env, _array, pointer, JNI_FALSE); - } } /* void glOrthof ( GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar ) */ @@ -3001,7 +3033,13 @@ android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I jint _remaining; GLvoid *pointer = (GLvoid *) 0; - pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining); + if (pointer_buf) { + pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + if ( ! pointer ) { + _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); + return; + } + } glTexCoordPointerBounds( (GLint)size, (GLenum)type, @@ -3009,9 +3047,6 @@ android_glTexCoordPointerBounds__IIILjava_nio_Buffer_2I (GLvoid *)pointer, (GLsizei)remaining ); - if (_array) { - releasePointer(_env, _array, pointer, JNI_FALSE); - } } /* void glTexEnvf ( GLenum target, GLenum pname, GLfloat param ) */ @@ -3356,7 +3391,13 @@ android_glVertexPointerBounds__IIILjava_nio_Buffer_2I jint _remaining; GLvoid *pointer = (GLvoid *) 0; - pointer = (GLvoid *)getPointer(_env, pointer_buf, &_array, &_remaining); + if (pointer_buf) { + pointer = (GLvoid *) _env->GetDirectBufferAddress(pointer_buf); + if ( ! pointer ) { + _env->ThrowNew(IAEClass, "Must use a native order direct Buffer"); + return; + } + } glVertexPointerBounds( (GLint)size, (GLenum)type, @@ -3364,9 +3405,6 @@ android_glVertexPointerBounds__IIILjava_nio_Buffer_2I (GLvoid *)pointer, (GLsizei)remaining ); - if (_array) { - releasePointer(_env, _array, pointer, JNI_FALSE); - } } /* void glViewport ( GLint x, GLint y, GLsizei width, GLsizei height ) */ diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 7ebc896..bff6b9d 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -803,6 +803,14 @@ android:description="@string/permdesc_runSetActivityWatcher" android:protectionLevel="signature" /> + <!-- Allows an application to watch and control how activities are + started globally in the system. Only for is in debugging + (usually the monkey command). --> + <permission android:name="android.permission.SHUTDOWN" + android:label="@string/permlab_shutdown" + android:description="@string/permdesc_shutdown" + android:protectionLevel="signature" /> + <!-- Allows an application to retrieve the current state of keys and switches. This is only for use by the system.--> <permission android:name="android.permission.READ_INPUT_STATE" diff --git a/core/res/res/drawable/divider_horizontal_bright.9.png b/core/res/res/drawable/divider_horizontal_bright.9.png Binary files differindex 144fc22..30c9b2b 100644 --- a/core/res/res/drawable/divider_horizontal_bright.9.png +++ b/core/res/res/drawable/divider_horizontal_bright.9.png diff --git a/core/res/res/drawable/divider_horizontal_dark.9.png b/core/res/res/drawable/divider_horizontal_dark.9.png Binary files differindex 08838ca..ce21acd 100644 --- a/core/res/res/drawable/divider_horizontal_dark.9.png +++ b/core/res/res/drawable/divider_horizontal_dark.9.png diff --git a/core/res/res/drawable/search_dropdown_background_apps.9.png b/core/res/res/drawable/search_dropdown_background_apps.9.png Binary files differnew file mode 100644 index 0000000..56b697d --- /dev/null +++ b/core/res/res/drawable/search_dropdown_background_apps.9.png diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 54da326..1319c77 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -753,9 +753,28 @@ {@link #AndroidManifest manifest} tag. --> <declare-styleable name="AndroidManifestUsesSdk" parent="AndroidManifest"> <!-- This is the minimum SDK version number that the application - requires. Currently there is only one SDK version, 1. If - not supplied, the application will work on any SDK. --> - <attr name="minSdkVersion" format="integer" /> + requires. This number is an abstract integer, from the list + in {@link android.os.Build.VERSION_CODES} If + not supplied, the application will work on any SDK. This + may also be string (such as "Donut") if the application was built + against a development branch, in which case it will only work against + the development builds. --> + <attr name="minSdkVersion" format="integer|string" /> + <!-- This is the SDK version number that the application is targeting. + It is able to run on older versions (down to minSdkVersion), but + was explicitly tested to work with the version specified here. + Specifying this version allows the platform to disable compatibility + code that are not required or enable newer features that are not + available to older applications. This may also be a string + (such as "Donut") if this is built against a development + branch, in which case minSdkVersion is also forced to be that + string. --> + <attr name="targetSdkVersion" format="integer|string" /> + <!-- This is the maximum SDK version number that an application works + on. You can use this to ensure your application is filtered out + of later versions of the platform when you know you have + incompatibility with them. --> + <attr name="maxSdkVersion" format="integer" /> </declare-styleable> <!-- The <code>uses-libraries</code> specifies a shared library that this diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 9e4c6a9..df5d879 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1087,7 +1087,7 @@ <public type="integer" name="config_longAnimTime" id="0x010e0002" /> <!-- =============================================================== - Resources added in version 4 of the platform. + Resources added in Donut. =============================================================== --> <eat-comment /> @@ -1097,6 +1097,8 @@ <public type="attr" name="searchSuggestThreshold" id="0x0101026d" /> <public type="attr" name="includeInGlobalSearch" id="0x0101026e" /> <public type="attr" name="onClick" id="0x0101026f" /> + <public type="attr" name="targetSdkVersion" id="0x01010270" /> + <public type="attr" name="maxSdkVersion" id="0x01010271" /> <public type="anim" name="anticipate_interpolator" id="0x010a0007" /> <public type="anim" name="overshoot_interpolator" id="0x010a0008" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 6e2da4b..331ef1a 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -467,6 +467,12 @@ the system, and steal or corrupt any data on it.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_shutdown">partial shutdown</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_shutdown">Puts the activity manager into a shutdown + state. Does not perform a complete shutdown.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_runSetActivityWatcher">monitor and control all application launching</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_runSetActivityWatcher">Allows an application to |