diff options
21 files changed, 639 insertions, 139 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index b759de0..1b2326a 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -30,14 +30,15 @@ import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; +import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.res.AssetManager; import android.content.res.Resources; import android.net.Uri; +import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; -import android.provider.Settings; import java.io.File; import java.lang.reflect.Field; @@ -228,7 +229,7 @@ public final class Pm { String filter = nextArg(); try { - List<PackageInfo> packages = mPm.getInstalledPackages(getFlags); + final List<PackageInfo> packages = getInstalledPackages(mPm, getFlags); int count = packages.size(); for (int p = 0 ; p < count ; p++) { @@ -256,6 +257,22 @@ public final class Pm { } } + @SuppressWarnings("unchecked") + private List<PackageInfo> getInstalledPackages(IPackageManager pm, int flags) + throws RemoteException { + final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>(); + PackageInfo lastItem = null; + ParceledListSlice<PackageInfo> slice; + + do { + final String lastKey = lastItem != null ? lastItem.packageName : null; + slice = pm.getInstalledPackages(flags, lastKey); + lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR); + } while (!slice.isLastSlice()); + + return packageInfos; + } + /** * Lists all of the features supported by the current device. * diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 50e56c7..5926929 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -35,6 +35,7 @@ import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager; +import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; import android.content.pm.ProviderInfo; @@ -44,6 +45,7 @@ import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.Parcel; import android.os.Process; import android.os.RemoteException; import android.util.Log; @@ -378,19 +380,41 @@ final class ApplicationPackageManager extends PackageManager { throw new NameNotFoundException("No shared userid for user:"+sharedUserName); } + @SuppressWarnings("unchecked") @Override public List<PackageInfo> getInstalledPackages(int flags) { try { - return mPM.getInstalledPackages(flags); + final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>(); + PackageInfo lastItem = null; + ParceledListSlice<PackageInfo> slice; + + do { + final String lastKey = lastItem != null ? lastItem.packageName : null; + slice = mPM.getInstalledPackages(flags, lastKey); + lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR); + } while (!slice.isLastSlice()); + + return packageInfos; } catch (RemoteException e) { throw new RuntimeException("Package manager has died", e); } } + @SuppressWarnings("unchecked") @Override public List<ApplicationInfo> getInstalledApplications(int flags) { try { - return mPM.getInstalledApplications(flags); + final List<ApplicationInfo> applicationInfos = new ArrayList<ApplicationInfo>(); + ApplicationInfo lastItem = null; + ParceledListSlice<ApplicationInfo> slice; + + do { + final String lastKey = lastItem != null ? lastItem.packageName : null; + slice = mPM.getInstalledApplications(flags, lastKey); + lastItem = slice.populateList(applicationInfos, ApplicationInfo.CREATOR); + } while (!slice.isLastSlice()); + + return applicationInfos; } catch (RemoteException e) { throw new RuntimeException("Package manager has died", e); } diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 06c1ecb..5ba5fe1 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -16,16 +16,6 @@ package android.content; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Set; - import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; @@ -37,6 +27,15 @@ import android.util.Printer; import com.android.internal.util.XmlUtils; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Set; + /** * Structured description of Intent values to be matched. An IntentFilter can * match against actions, categories, and data (either via its type, scheme, @@ -755,7 +754,7 @@ public class IntentFilter implements Parcelable { } /** - * Add a new Intent data oath to match against. The filter must + * Add a new Intent data path to match against. The filter must * include one or more schemes (via {@link #addDataScheme}) <em>and</em> * one or more authorities (via {@link #addDataAuthority}) for the * path to be considered. If any paths are diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index fbf8f92..20b1b50 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -30,6 +30,7 @@ import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageStatsObserver; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; +import android.content.pm.ParceledListSlice; import android.content.pm.ProviderInfo; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; @@ -109,9 +110,21 @@ interface IPackageManager { List<ResolveInfo> queryIntentServices(in Intent intent, String resolvedType, int flags); - List<PackageInfo> getInstalledPackages(int flags); + /** + * This implements getInstalledPackages via a "last returned row" + * mechanism that is not exposed in the API. This is to get around the IPC + * limit that kicks in when flags are included that bloat up the data + * returned. + */ + ParceledListSlice getInstalledPackages(int flags, in String lastRead); - List<ApplicationInfo> getInstalledApplications(int flags); + /** + * This implements getInstalledApplications via a "last returned row" + * mechanism that is not exposed in the API. This is to get around the IPC + * limit that kicks in when flags are included that bloat up the data + * returned. + */ + ParceledListSlice getInstalledApplications(int flags, in String lastRead); /** * Retrieve all applications that are marked as persistent. diff --git a/core/java/android/content/pm/ParceledListSlice.aidl b/core/java/android/content/pm/ParceledListSlice.aidl new file mode 100755 index 0000000..c02cc6a --- /dev/null +++ b/core/java/android/content/pm/ParceledListSlice.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2011, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.pm; + +parcelable ParceledListSlice; diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java new file mode 100644 index 0000000..f3a98db --- /dev/null +++ b/core/java/android/content/pm/ParceledListSlice.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.List; + +/** + * Builds up a parcel that is discarded when written to another parcel or + * written to a list. This is useful for API that sends huge lists across a + * Binder that may be larger than the IPC limit. + * + * @hide + */ +public class ParceledListSlice<T extends Parcelable> implements Parcelable { + /* + * TODO get this number from somewhere else. For now set it to a quarter of + * the 1MB limit. + */ + private static final int MAX_IPC_SIZE = 256 * 1024; + + private Parcel mParcel; + + private int mNumItems; + + private boolean mIsLastSlice; + + public ParceledListSlice() { + mParcel = Parcel.obtain(); + } + + private ParceledListSlice(Parcel p, int numItems, boolean lastSlice) { + mParcel = p; + mNumItems = numItems; + mIsLastSlice = lastSlice; + } + + @Override + public int describeContents() { + return 0; + } + + /** + * Write this to another Parcel. Note that this discards the internal Parcel + * and should not be used anymore. This is so we can pass this to a Binder + * where we won't have a chance to call recycle on this. + */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mNumItems); + dest.writeInt(mIsLastSlice ? 1 : 0); + + if (mNumItems > 0) { + final int parcelSize = mParcel.dataSize(); + dest.writeInt(parcelSize); + dest.appendFrom(mParcel, 0, parcelSize); + } + + mNumItems = 0; + mParcel.recycle(); + mParcel = null; + } + + /** + * Appends a parcel to this list slice. + * + * @param item Parcelable item to append to this list slice + * @return true when the list slice is full and should not be appended to + * anymore + */ + public boolean append(T item) { + if (mParcel == null) { + throw new IllegalStateException("ParceledListSlice has already been recycled"); + } + + item.writeToParcel(mParcel, PARCELABLE_WRITE_RETURN_VALUE); + mNumItems++; + + return mParcel.dataSize() > MAX_IPC_SIZE; + } + + /** + * Populates a list and discards the internal state of the + * ParceledListSlice in the process. The instance should + * not be used anymore. + * + * @param list list to insert items from this slice. + * @param creator creator that knows how to unparcel the + * target object type. + * @return the last item inserted into the list or null if none. + */ + public T populateList(List<T> list, Creator<T> creator) { + mParcel.setDataPosition(0); + + T item = null; + for (int i = 0; i < mNumItems; i++) { + item = creator.createFromParcel(mParcel); + list.add(item); + } + + mParcel.recycle(); + mParcel = null; + + return item; + } + + /** + * Sets whether this is the last list slice in the series. + * + * @param lastSlice + */ + public void setLastSlice(boolean lastSlice) { + mIsLastSlice = lastSlice; + } + + /** + * Returns whether this is the last slice in a series of slices. + * + * @return true if this is the last slice in the series. + */ + public boolean isLastSlice() { + return mIsLastSlice; + } + + @SuppressWarnings("unchecked") + public static final Parcelable.Creator<ParceledListSlice> CREATOR = + new Parcelable.Creator<ParceledListSlice>() { + public ParceledListSlice createFromParcel(Parcel in) { + final int numItems = in.readInt(); + final boolean lastSlice = in.readInt() == 1; + + if (numItems > 0) { + final int parcelSize = in.readInt(); + + // Advance within this Parcel + int offset = in.dataPosition(); + in.setDataPosition(offset + parcelSize); + + Parcel p = Parcel.obtain(); + p.setDataPosition(0); + p.appendFrom(in, offset, parcelSize); + p.setDataPosition(0); + + return new ParceledListSlice(p, numItems, lastSlice); + } else { + return new ParceledListSlice(); + } + } + + public ParceledListSlice[] newArray(int size) { + return new ParceledListSlice[size]; + } + }; +} diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 6fd1d00..cdb622c 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -23,7 +23,6 @@ import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; -import android.util.Slog; import android.util.SparseArray; import java.lang.ref.WeakReference; @@ -100,10 +99,11 @@ public class StorageManager private final ObbActionListener mObbActionListener = new ObbActionListener(); private class ObbActionListener extends IObbActionListener.Stub { + @SuppressWarnings("hiding") private SparseArray<ObbListenerDelegate> mListeners = new SparseArray<ObbListenerDelegate>(); @Override - public void onObbResult(String filename, int nonce, int status) throws RemoteException { + public void onObbResult(String filename, int nonce, int status) { final ObbListenerDelegate delegate; synchronized (mListeners) { delegate = mListeners.get(nonce); @@ -147,8 +147,8 @@ public class StorageManager mHandler = new Handler(mTgtLooper) { @Override public void handleMessage(Message msg) { - final OnObbStateChangeListener listener = getListener(); - if (listener == null) { + final OnObbStateChangeListener changeListener = getListener(); + if (changeListener == null) { return; } @@ -156,7 +156,7 @@ public class StorageManager if (msg.what == StorageEvent.EVENT_OBB_STATE_CHANGED) { ObbStateChangedStorageEvent ev = (ObbStateChangedStorageEvent) e; - listener.onObbStateChange(ev.path, ev.state); + changeListener.onObbStateChange(ev.path, ev.state); } else { Log.e(TAG, "Unsupported event " + msg.what); } diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java index bc6e993..bc4208a 100644 --- a/core/java/android/os/storage/StorageVolume.java +++ b/core/java/android/os/storage/StorageVolume.java @@ -16,10 +16,8 @@ package android.os.storage; -import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import android.util.Log; /** * A class representing a storage volume @@ -27,7 +25,7 @@ import android.util.Log; */ public class StorageVolume implements Parcelable { - private static final String TAG = "StorageVolume"; + //private static final String TAG = "StorageVolume"; private final String mPath; private final String mDescription; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 8e3e699..c315884 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -11251,6 +11251,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility /** * Request that the visibility of the status bar be changed. + * @param visibility Either {@link #STATUS_BAR_VISIBLE} or {@link #STATUS_BAR_HIDDEN}. */ public void setSystemUiVisibility(int visibility) { if (visibility != mSystemUiVisibility) { @@ -11263,11 +11264,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility /** * Returns the status bar visibility that this view has requested. + * @return Either {@link #STATUS_BAR_VISIBLE} or {@link #STATUS_BAR_HIDDEN}. */ public int getSystemUiVisibility() { return mSystemUiVisibility; } + /** + * Set a listener to receive callbacks when the visibility of the system bar changes. + * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks. + */ public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) { mOnSystemUiVisibilityChangeListener = l; if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) { diff --git a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java index 965022e..4773ce4 100644 --- a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java +++ b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java @@ -14,6 +14,7 @@ import android.os.ServiceManager; import android.os.storage.IMountService; import android.os.storage.StorageEventListener; import android.os.storage.StorageManager; +import android.os.storage.StorageVolume; import android.util.Log; import android.view.WindowManager; import android.widget.Toast; @@ -32,6 +33,9 @@ public class ExternalStorageFormatter extends Service public static final String EXTRA_ALWAYS_RESET = "always_reset"; + // If non-null, the volume to format. Otherwise, will use the default external storage directory + private StorageVolume mStorageVolume; + public static final ComponentName COMPONENT_NAME = new ComponentName("android", ExternalStorageFormatter.class.getName()); @@ -80,6 +84,8 @@ public class ExternalStorageFormatter extends Service mAlwaysReset = true; } + mStorageVolume = intent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME); + if (mProgressDialog == null) { mProgressDialog = new ProgressDialog(this); mProgressDialog.setIndeterminate(true); @@ -115,7 +121,9 @@ public class ExternalStorageFormatter extends Service @Override public void onCancel(DialogInterface dialog) { IMountService mountService = getMountService(); - String extStoragePath = Environment.getExternalStorageDirectory().toString(); + String extStoragePath = mStorageVolume == null ? + Environment.getExternalStorageDirectory().toString() : + mStorageVolume.getPath(); try { mountService.mountVolume(extStoragePath); } catch (RemoteException e) { @@ -133,12 +141,16 @@ public class ExternalStorageFormatter extends Service } void updateProgressState() { - String status = Environment.getExternalStorageState(); + String status = mStorageVolume == null ? + Environment.getExternalStorageState() : + mStorageManager.getVolumeState(mStorageVolume.getPath()); if (Environment.MEDIA_MOUNTED.equals(status) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status)) { updateProgressDialog(R.string.progress_unmounting); IMountService mountService = getMountService(); - String extStoragePath = Environment.getExternalStorageDirectory().toString(); + final String extStoragePath = mStorageVolume == null ? + Environment.getExternalStorageDirectory().toString() : + mStorageVolume.getPath(); try { mountService.unmountVolume(extStoragePath, true); } catch (RemoteException e) { @@ -149,9 +161,12 @@ public class ExternalStorageFormatter extends Service || Environment.MEDIA_UNMOUNTABLE.equals(status)) { updateProgressDialog(R.string.progress_erasing); final IMountService mountService = getMountService(); - final String extStoragePath = Environment.getExternalStorageDirectory().toString(); + final String extStoragePath = mStorageVolume == null ? + Environment.getExternalStorageDirectory().toString() : + mStorageVolume.getPath(); if (mountService != null) { new Thread() { + @Override public void run() { boolean success = false; try { @@ -185,7 +200,7 @@ public class ExternalStorageFormatter extends Service } }.start(); } else { - Log.w("MediaFormat", "Unable to locate IMountService"); + Log.w(TAG, "Unable to locate IMountService"); } } else if (Environment.MEDIA_BAD_REMOVAL.equals(status)) { fail(R.string.media_bad_removal); diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml index 70af265..5684335 100644 --- a/core/res/res/layout/screen_action_bar.xml +++ b/core/res/res/layout/screen_action_bar.xml @@ -43,9 +43,4 @@ This is an optimized layout for a screen with the Action Bar enabled. android:layout_weight="1" android:foregroundGravity="fill_horizontal|top" android:foreground="?android:attr/windowContentOverlay" /> - <LinearLayout android:id="@+id/lower_action_context_bar" - android:layout_width="match_parent" - android:layout_height="wrap_content" - style="?android:attr/actionBarStyle" - android:visibility="gone" /> </LinearLayout> diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml index b486ee7..89f0d89 100644 --- a/core/res/res/layout/screen_action_bar_overlay.xml +++ b/core/res/res/layout/screen_action_bar_overlay.xml @@ -46,10 +46,4 @@ the Action Bar enabled overlaying application content. android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/action_bar_container" /> - <LinearLayout android:id="@+id/lower_action_context_bar" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="bottom" - style="?android:attr/actionBarStyle" - android:visibility="gone" /> </RelativeLayout> diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml index d05685c..e8d9fde 100644 --- a/core/res/res/values/ids.xml +++ b/core/res/res/values/ids.xml @@ -74,4 +74,5 @@ <item type="id" name="rowTypeId" /> <item type="id" name="up" /> <item type="id" name="action_menu_divider" /> + <item type="id" name="lower_action_context_bar" /> </resources> diff --git a/docs/html/guide/developing/tools/adb.jd b/docs/html/guide/developing/tools/adb.jd index e891ccd..a109dc8 100644 --- a/docs/html/guide/developing/tools/adb.jd +++ b/docs/html/guide/developing/tools/adb.jd @@ -35,45 +35,9 @@ parent.link=index.html </div> </div> -<!-- -<p>Android Debug Bridge (adb) is a versatile tool that </a>. </p> - -<p>Some of ways you can use adb include:</p> - -<ul> - -</ul> -<p>The sections below introduce adb and describe many of its common uses. </p> - -<h2>Contents</h2> -<dl> -<dt><a href="#overview">Overview</a></dt> -<dt><a href="#issuingcommands">Issuing adb Commands</a></dt> -<dt><a href="#devicestatus">Querying for Emulator/Device Instances</a></dt> -<dt><a href="#directingcommands">Directing Commands to a Specific Emulator/Device Instance</a></dt> -<dt><a href="#move">Installing an Application</a></dt> -<dt><a href="#forwardports">Forwarding Ports</a></dt> -<dt><a href="#copyfiles">Copying Files to or from an Emulator/Device Instance</a></dt> -<dt><a href="#commandsummary">Listing of adb Commands </a></dt> -<dt><a href="#shellcommands">Issuing Shell Commands</a></dt> - <dd><a href="#sqlite">Examining sqlite3 Databases from a Remote Shell</a></dd> - <dd><a href="#monkey">UI/Application Exerciser Monkey</a></dd> - <dd><a href="#othershellcommands">Other Shell Commands</a></dd> -<dt><a href="#logcat">Enabling logcat Logging</a> </dt> - <dd><a href="#usinglogcat">Using logcat Commands</a></dd> - <dd><a href="#filteringoutput">Filtering Log Output</a></dd> - <dd><a href="#outputformat">Controlling Log Output Format</a></dd> - <dd><a href="#alternativebuffers">Viewing Alternative Log Buffers</a></dd> - <dd><a href="#stdout">Viewing stdout and stderr</a></dd> - <dd><a href="#logcatoptions">Listing of logcat Command Options</a></dd> -<dt><a href="#stopping">Stopping the adb Server</a> </dt> -</dl> - -<a name="overview"></a> - -<h2>Overview</h2> ---> -<p>Android Debug Bridge (adb) is a versatile tool lets you manage the state of an emulator instance or Android-powered device. It is a client-server program that includes three components: </p> +<p>Android Debug Bridge (adb) is a versatile command line tool that lets you communicate with an +emulator instance or connected Android-powered device. It is a client-server program that includes +three components: </p> <ul> <li>A client, which runs on your development machine. You can invoke a client from a shell by issuing an adb command. Other Android tools such as the ADT plugin and DDMS also create adb clients. </li> diff --git a/docs/html/guide/practices/optimizing-for-3.0.jd b/docs/html/guide/practices/optimizing-for-3.0.jd index 5cd519b..e968372 100644 --- a/docs/html/guide/practices/optimizing-for-3.0.jd +++ b/docs/html/guide/practices/optimizing-for-3.0.jd @@ -22,6 +22,14 @@ page.title=Optimizing Apps for Android 3.0 </li> </ol> +<h2>See also</h2> + +<ol> + <li><a +href="{@docRoot}sdk/compatibility-library.html">Compatibility Library</a></li> + <li><a href="http://code.google.com/p/iosched/">Google I/O App source code</a></li> +</ol> + </div> </div> @@ -172,7 +180,8 @@ visual elements. This is the standard theme for applications built for Android 3 application will look and feel consistent with the system and other applications when it is enabled.</p> <p>Additionally, when an activity uses the holographic theme, the system enables the <a -href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> for the activity. The Action Bar +href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> for the activity and removes the +Options Menu button in the system bar. The Action Bar replaces the traditional title bar at the top of the activity window and provides the user access to the activity's Options Menu.</p> </li> @@ -233,27 +242,26 @@ for Screen Independence</a>.</p> - - <h2 id="Upgrading">Upgrading or Developing a New App for Tablets</h2> <div class="sidebox-wrapper"> <div class="sidebox"> - <h3>Use new APIs and remain backward-compatible</h3> + <h3>Use the Compatibility Library to remain backward-compatible</h3> <p>It is possible for you to upgrade your application with some new APIs <em>and</em> remain compatible with older versions of Android. Usually, this requires that you use techniques such as reflection to check for the availability of certain APIs at runtime. However, to help you add features from Android 3.0 without requiring you to change your <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a> -or build target, we're providing a static library called the "Android Compatibility package" +or build target, we're providing a static library called the <a +href="{@docRoot}sdk/compatibility-library.html">Compatibility Library</a> (downloadable from the AVD and SDK Manager).</p> <p>This library includes APIs for <a href="{@docRoot}guide/topics/fundamentals/fragments.html">fragments</a>, <a href="{@docRoot}guide/topics/fundamentals/loaders.html">loaders</a>, and some updated classes. By simply adding this library to your Android project, you can use these APIs in your application and -remain compatible with Android 1.6. For more information, see the blog post, <a -href="http://android-developers.blogspot.com/2011/03/fragments-for-all.html">Fragments for -All</a>.</p> +remain compatible with Android 1.6. For information about how to get the library and start +using it in your application, see the <a +href="{@docRoot}sdk/compatibility-library.html">Compatibility Library</a> document.</p> </div> </div> @@ -380,7 +388,6 @@ new graphics engine called Renderscript, and more.</p> href="{@docRoot}sdk/android-3.0.html">Android 3.0 Platform</a> document.</p> - <h3>Look at some samples</h3> <p>Many of the new features and APIs that are described above and in the <a diff --git a/docs/html/sdk/android-2.3.4.jd b/docs/html/sdk/android-2.3.4.jd index e5765d3..4cb44b9 100644 --- a/docs/html/sdk/android-2.3.4.jd +++ b/docs/html/sdk/android-2.3.4.jd @@ -128,7 +128,7 @@ function toggleDiv(link) { <a href="{@docRoot}sdk/android-2.3.3.html">Android 2.3.3 version notes</a>.</p> -<h2 id="openaccessory">Open Accessory Library</h3> +<h2 id="openaccessory">Open Accessory Library</h2> <p><em>Open Accessory</em> is a new capability for integrating connected peripherals with applications running on the platform. The capability @@ -241,7 +241,7 @@ built-in applications:</p> <li>Camera</li> <li>Clock</li> <li>Contacts</li> -<li>Cusom Locale</li> +<li>Custom Locale</li> <li>Dev Tools</li> <li>Downloads</li> <li>Email</li> @@ -309,6 +309,7 @@ descriptor).</p> </ul> </td> <td style="border:0;padding-bottom:0;margin-bottom:0;padding-left:5em;"> +<ul> <li>Croatian, Croatia (hr_HR)</li> <li>Hungarian, Hungary (hu_HU)</li> <li>Indonesian, Indonesia (id_ID)</li> @@ -337,6 +338,7 @@ descriptor).</p> <li>Vietnamese, Vietnam (vi_VN)</li> <li>Chinese, PRC (zh_CN)</li> <li>Chinese, Taiwan (zh_TW)</li> +</ul> </td> </tr> </table> diff --git a/docs/html/sdk/compatibility-library.jd b/docs/html/sdk/compatibility-library.jd new file mode 100644 index 0000000..d4669e5 --- /dev/null +++ b/docs/html/sdk/compatibility-library.jd @@ -0,0 +1,224 @@ +page.title=Compatibility Library + +@jd:body + +<div id="qv-wrapper"> +<div id="qv"> + +<h2>In this document</h2> +<ol> + <li><a href="#Notes">Revisions</a></li> + <li><a href="#Installing">Installing the Compatibility Library</a></li> + <li><a href="#SettingUp">Setting Up a Project to Use the Library</a></li> + <li><a href="#Using">Using Some of the Library APIs</a></li> + <li><a href="#Samples">Samples</a></li> +</ol> + +<h2>See also</h2> +<ol> + <li><a +href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing Apps for Android 3.0</a></li> + <li><a href="http://code.google.com/p/iosched/">Google I/O App source code</a></li> +</ol> + +</div> +</div> + +<p><em>Minimum API level supported:</em> <b>4</b></p> + +<p>The Compatibility Library is a static library you can add to your Android application in order to +use APIs not available in older versions of the Android platform. The primary goal of the library is +to provide APIs introduced in Andriod 3.0 for older versions of Android so that all applications can +use them.</p> + +<p>If you're not able to use APIs introduced in Android 3.0 directly, because you want to remain +backward-compatible, the Compatibility Library provides your application access to self-contained +versions of some of the latest APIs that you can use with older versions of Android. Most +importantly, the library provides implementations of the {@link android.app.Fragment} and {@link +android.content.Loader} APIs, so you can use them in a way that's compatible with devices running +Android 1.6 (API level 4) and higher. Thus, you can more easily create a single APK that supports a +majority of devices and provide larger devices (such as tablets) a fully optimized experience by +using <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> in your activity +design.</p> + + +<h2 id="Notes">Revisions</h2> + +<p>The sections below provide notes about successive releases of +the Compatibility Library, as denoted by revision number.</p> + + +<div class="toggle-content open"> + + <p><a href="#" onclick="return toggleContent(this)"> + <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" /> + Compatibility Library, revision 2 (May 2011) + </a></p> + + <div class="toggle-content-toggleme" style="padding-left:2em"> + <dl> + <dt>Changes:</dt> + <dd> + <ul> + <li>Support for fragment animations.</li> + <li>Fix {@code Fragment.onActivityResult()} bug.</li> + </ul> + </dd> + </dl> + </div> + +</div> + + +<div class="toggle-content closed"> + + <p><a href="#" onclick="return toggleContent(this)"> + <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" /> + Compatibility Library, revision 1 (March 2011) + </a></p> + + <div class="toggle-content-toggleme" style="padding-left:2em"> + <p>Initial release of the library.</p> + </div> + +</div> + + + +<h2 id="Installing">Installing the Compatibility Library</h2> + +<p>The Compatibility Library is provided as a downloadable package from the Android SDK and AVD +Manager. To install the library:</p> + +<ol> + <li>Launch the SDK and AVD Manager. + <p>From Eclipse, you can select <strong>Window</strong> +> <strong>Android SDK and AVD Manager</strong>. Or, launch {@code SDK Manager.exe} from +the {@code <sdk>/} directory (on Windows only) or {@code android} from the {@code +<sdk>/tools/} directory.</p></li> + <li>Expand the Android Repository, check <strong>Android Compatibility package</strong> +and click <strong>Install selected</strong>.</li> + <li>Proceed to install the package.</li> +</ol> + +<p>When done, all files (including source code, samples, and the {@code .jar} file) are saved +into the <code><sdk>/extras/android/compatibility/</code> directory. The next directory +name is {@code v4}, which indicates the lowest compatible version for the library within. That +is, the code in {@code v4/} supports API level 4 and above. (There may be future libraries that +have a different minimum version, so they will be saved alongside this one.)</p> + + +<h2 id="SettingUp">Setting Up a Project to Use the Library</h2> + +<p>To add the Compatibility Library to your Android project:</p> +<ol> + <li>In your Android project, create a directory named {@code libs} at the root of your +project (next to {@code src/}, {@code res/}, etc.)</li> + <li>Navigate to {@code <sdk>/extras/android/compatibility/v4/}.</li> + <li>Copy the {@code android-support-v4.jar} file into your project {@code libs/} directory.</li> + <li>Add the JAR to your project build path. In Eclipse, right-click the JAR file in the +Package Explorer, select <strong>Build Path</strong> > <strong>Add to Build Path</strong>. +You should then see the JAR file appear in a new directory called Referenced Libraries.</li> +</ol> + +<p>Your application is now ready to use fragments, loaders and other APIs from the library. All the +provided APIs are in the {@code android.support.v4} package.</p> + +<p class="warning"><strong>Warning:</strong> Be certain that you not confuse the standard +{@code android} packages with those in {@code android.support.v4}. Some code completion tools might +get this wrong, especially if you're building against recent versions of the platform. To be safe, +keep your build target set to the same version as you have defined for your <a +href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a> +and double check the import statements for classes that are duplicated in the Compatibility +Library, such as {@code SimpleCursorAdapter}.</p> + + +<h2 id="Using">Using Some of the Library APIs</h2> + +<p>The Compatibility Library provides access to several classes introduced with Android 3.0, plus +some updated version of existing classes. Some of the most useful and notable classes in the +library are:</p> + +<ul> + <li>{@link android.app.Fragment}</li> + <li>{@link android.app.FragmentManager}</li> + <li>{@link android.app.FragmentTransaction}</li> + <li>{@link android.app.ListFragment}</li> + <li>{@link android.app.DialogFragment}</li> + <li>{@link android.app.LoaderManager}</li> + <li>{@link android.content.Loader}</li> + <li>{@link android.content.AsyncTaskLoader}</li> + <li>{@link android.content.CursorLoader}</li> +</ul> + +<p>For each of the classes above (and others not listed), the APIs work almost exactly the same +as the counterparts in the latest version of the Android platform. Thus, you can usually refer to +the latest reference documentation for information about the supported APIs. There are some +differences, however. Most notably:</p> + +<ul> + <li>When creating an activity to use fragments, you must declare your activity to extend the +{@code FragmentActivity} class (instead of the traditional {@link android.app.Activity} +class).</li> + <li>To manage your fragments and loaders, you must use the methods {@code +FragmentActivity.getSupportFragmentManager()} and {@code +FragmentActivity.getSupportLoaderManager()} (instead of the {@link +android.app.Activity#getFragmentManager()} and {@link android.app.Activity#getLoaderManager()} +methods).</li> + <li>The {@link android.app.ActionBar} is <strong>not supported</strong> by the library. +However, when creating your <a href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options +Menu</a>, you can declare which items should be added to the Action Bar when it's available (on +Android 3.0 or later). You can do so with the {@code MenuCompat.setShowAsAction()} method. For +example: +<pre> +public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.options, menu); + MenuCompat.setShowAsAction(menu.findItem(R.id.action_search), 1); + return true; +} +</pre> +</li> +</ul> + +<p>The Compatibility Library currently does not provide reference documentation for the included +APIs. To generate your own set, using the {@code javadoc} tool, perform the +following from a command line:</p> + +<pre class="no-pretty-print"> +cd <sdk>/extras/android/compatibility/v4/ +mkdir docs +javadoc -sourcepath src/java/ -subpackages android.support.v4 -d docs +</pre> +<p>Open the {@code docs/index.html} file to begin browsing the generated documentation.</p> + + +<div class="note"><p><strong>Tip:</strong> To enable the Holographic theme on devices +running Android 3.0 or higher, declare in your manifest file that your application targets +API level 11. For example:</p> +<pre> +<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="11" /> +</pre> +<p>This way, your application automatically receives the Holographic theme and the Action Bar for +each activity when running on Android 3.0 and higher.</p> +</div> + +<p>For more information about how you can optimize your application for the latest +Android-powered devices, read <a href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing +Apps for Android 3.0</a>.</p> + + +<h2 id="Samples">Samples</h2> + +<p>If you want to see some sample code that uses the Compatibility Library, take a look at the +<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/support/index.html">API +Demos</a> sample code that's included with the Samples package you can download from the AVD and SDK +Manager.</p> + +<p>Additionally, the <a href="http://code.google.com/p/iosched/">Google I/O App</a> is a complete +application that uses the library to provide a single APK for both handsets and tablets and also +demonstrates some of Android's best practices in Android UI design.</p> + + + + diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs index 11f29b1..d1c0679 100644 --- a/docs/html/sdk/sdk_toc.cs +++ b/docs/html/sdk/sdk_toc.cs @@ -138,6 +138,8 @@ class="new">new!</span></li> <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r11</a> <span class="new">new!</span></li> <li><a href="<?cs var:toroot ?>sdk/win-usb.html">Google USB Driver, r4</a></li> + <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Compatibility Library, r2</a> <span +class="new">new!</span></li> </ul> </li> <li> diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index d9d7d23..ffcae1c 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -63,7 +63,7 @@ struct Blender { // In this array, the index of each Blender equals the value of the first // entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode] static const Blender gBlends[] = { - { SkXfermode::kClear_Mode, GL_ZERO, GL_ZERO }, + { SkXfermode::kClear_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO }, { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE }, { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, @@ -81,7 +81,7 @@ static const Blender gBlends[] = { // this array's SrcOver blending mode is actually DstOver. You can refer to // createLayer() for more information on the purpose of this array. static const Blender gBlendsSwap[] = { - { SkXfermode::kClear_Mode, GL_ZERO, GL_ZERO }, + { SkXfermode::kClear_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, { SkXfermode::kSrc_Mode, GL_ZERO, GL_ONE }, { SkXfermode::kDst_Mode, GL_ONE, GL_ZERO }, { SkXfermode::kSrcOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE }, diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index 92d76be..3bd8215 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -148,7 +148,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int minimumPasswordLowerCase = DEF_MINIMUM_PASSWORD_LOWER_CASE; static final int DEF_MINIMUM_PASSWORD_LETTERS = 1; - int minimumPasswordLetters = DEF_MINIMUM_PASSWORD_LOWER_CASE; + int minimumPasswordLetters = DEF_MINIMUM_PASSWORD_LETTERS; static final int DEF_MINIMUM_PASSWORD_NUMERIC = 1; int minimumPasswordNumeric = DEF_MINIMUM_PASSWORD_NUMERIC; diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 4a66a40..dd5c2a9 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -55,6 +55,8 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageManager; import android.content.pm.PackageStats; +import android.content.pm.ParceledListSlice; + import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; @@ -75,6 +77,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Parcel; +import android.os.Parcelable; import android.os.RemoteException; import android.os.Environment; import android.os.FileObserver; @@ -2331,63 +2334,110 @@ class PackageManagerService extends IPackageManager.Stub { } } - public List<PackageInfo> getInstalledPackages(int flags) { - ArrayList<PackageInfo> finalList = new ArrayList<PackageInfo>(); + private static final int getContinuationPoint(final String[] keys, final String key) { + final int index; + if (key == null) { + index = 0; + } else { + final int insertPoint = Arrays.binarySearch(keys, key); + if (insertPoint < 0) { + index = -insertPoint; + } else { + index = insertPoint + 1; + } + } + return index; + } + + public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, String lastRead) { + final ParceledListSlice<PackageInfo> list = new ParceledListSlice<PackageInfo>(); + final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; + final String[] keys; synchronized (mPackages) { - if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { - Iterator<PackageSetting> i = mSettings.mPackages.values().iterator(); - while (i.hasNext()) { - final PackageSetting ps = i.next(); - PackageInfo psPkg = generatePackageInfoFromSettingsLP(ps.name, flags); - if(psPkg != null) { - finalList.add(psPkg); - } - } - } - else { - Iterator<PackageParser.Package> i = mPackages.values().iterator(); - while (i.hasNext()) { - final PackageParser.Package p = i.next(); - if (p.applicationInfo != null) { - PackageInfo pi = generatePackageInfo(p, flags); - if(pi != null) { - finalList.add(pi); - } + if (listUninstalled) { + keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]); + } else { + keys = mPackages.keySet().toArray(new String[mPackages.size()]); + } + + Arrays.sort(keys); + int i = getContinuationPoint(keys, lastRead); + final int N = keys.length; + + while (i < N) { + final String packageName = keys[i++]; + + PackageInfo pi = null; + if (listUninstalled) { + final PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps != null) { + pi = generatePackageInfoFromSettingsLP(ps.name, flags); + } + } else { + final PackageParser.Package p = mPackages.get(packageName); + if (p != null) { + pi = generatePackageInfo(p, flags); } } + + if (pi != null && !list.append(pi)) { + break; + } + } + + if (i == N) { + list.setLastSlice(true); } } - return finalList; + + return list; } - public List<ApplicationInfo> getInstalledApplications(int flags) { - ArrayList<ApplicationInfo> finalList = new ArrayList<ApplicationInfo>(); - synchronized(mPackages) { - if((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0) { - Iterator<PackageSetting> i = mSettings.mPackages.values().iterator(); - while (i.hasNext()) { - final PackageSetting ps = i.next(); - ApplicationInfo ai = generateApplicationInfoFromSettingsLP(ps.name, flags); - if(ai != null) { - finalList.add(ai); - } - } - } - else { - Iterator<PackageParser.Package> i = mPackages.values().iterator(); - while (i.hasNext()) { - final PackageParser.Package p = i.next(); - if (p.applicationInfo != null) { - ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags); - if(ai != null) { - finalList.add(ai); - } + public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, + String lastRead) { + final ParceledListSlice<ApplicationInfo> list = new ParceledListSlice<ApplicationInfo>(); + final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; + final String[] keys; + + synchronized (mPackages) { + if (listUninstalled) { + keys = mSettings.mPackages.keySet().toArray(new String[mSettings.mPackages.size()]); + } else { + keys = mPackages.keySet().toArray(new String[mPackages.size()]); + } + + Arrays.sort(keys); + int i = getContinuationPoint(keys, lastRead); + final int N = keys.length; + + while (i < N) { + final String packageName = keys[i++]; + + ApplicationInfo ai = null; + if (listUninstalled) { + final PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps != null) { + ai = generateApplicationInfoFromSettingsLP(ps.name, flags); + } + } else { + final PackageParser.Package p = mPackages.get(packageName); + if (p != null) { + ai = PackageParser.generateApplicationInfo(p, flags); } } + + if (ai != null && !list.append(ai)) { + break; + } + } + + if (i == N) { + list.setLastSlice(true); } } - return finalList; + + return list; } public List<ApplicationInfo> getPersistentApplications(int flags) { |