OSDN Git Service

Merge "LE: Add support for the HID-over-GATT profile (2/3)" into klp-dev
authorZhihai Xu <zhihaixu@google.com>
Thu, 15 Aug 2013 22:46:14 +0000 (22:46 +0000)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Thu, 15 Aug 2013 22:46:15 +0000 (22:46 +0000)
19 files changed:
core/java/android/app/NativeActivity.java
core/java/android/provider/DocumentsContract.java
core/jni/android/graphics/Bitmap.cpp
core/jni/android_app_NativeActivity.cpp
packages/DocumentsUI/AndroidManifest.xml
packages/DocumentsUI/res/values/strings.xml
packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java
packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
policy/src/com/android/internal/policy/impl/BarController.java [new file with mode: 0644]
policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
services/input/InputReader.h
wifi/java/android/net/wifi/WifiMonitor.java

index b84889f..4ca3747 100644 (file)
@@ -175,16 +175,20 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
                 ? savedInstanceState.getByteArray(KEY_NATIVE_SAVED_STATE) : null;
 
         mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
-                 getFilesDir().getAbsolutePath(), getObbDir().getAbsolutePath(),
-                 getExternalFilesDir(null).getAbsolutePath(),
-                 Build.VERSION.SDK_INT, getAssets(), nativeSavedState);
-        
+                getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
+                getAbsolutePath(getExternalFilesDir(null)),
+                Build.VERSION.SDK_INT, getAssets(), nativeSavedState);
+
         if (mNativeHandle == 0) {
             throw new IllegalArgumentException("Unable to load native library: " + path);
         }
         super.onCreate(savedInstanceState);
     }
 
+    private static String getAbsolutePath(File file) {
+        return (file != null) ? file.getAbsolutePath() : null;
+    }
+
     @Override
     protected void onDestroy() {
         mDestroyed = true;
index 0a16d73..909c4dd 100644 (file)
@@ -65,7 +65,7 @@ public final class DocumentsContract {
     public static final String META_DATA_DOCUMENT_PROVIDER = "android.content.DOCUMENT_PROVIDER";
 
     /** {@hide} */
-    public static final String ACTION_ROOTS_CHANGED = "android.provider.action.ROOTS_CHANGED";
+    public static final String ACTION_DOCUMENT_CHANGED = "android.provider.action.DOCUMENT_CHANGED";
 
     /**
      * {@link DocumentColumns#DOC_ID} value representing the root directory of a
@@ -496,7 +496,7 @@ public final class DocumentsContract {
      * This signal is used to invalidate internal caches.
      */
     public static void notifyRootsChanged(Context context, String authority) {
-        final Intent intent = new Intent(ACTION_ROOTS_CHANGED);
+        final Intent intent = new Intent(ACTION_DOCUMENT_CHANGED);
         intent.setData(buildRootsUri(authority));
         context.sendBroadcast(intent);
     }
index b03d12a..0ea3bf7 100644 (file)
@@ -222,8 +222,12 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
         }\r
     }\r
 \r
-    SkBitmap bitmap;\r
+    // ARGB_4444 is a deprecated format, convert automatically to 8888\r
+    if (config == SkBitmap::kARGB_4444_Config) {\r
+        config = SkBitmap::kARGB_8888_Config;\r
+    }\r
 \r
+    SkBitmap bitmap;\r
     bitmap.setConfig(config, width, height);\r
 \r
     jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);\r
@@ -232,8 +236,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
     }\r
 \r
     if (jColors != NULL) {\r
-        GraphicsJNI::SetPixels(env, jColors, offset, stride,\r
-                               0, 0, width, height, bitmap);\r
+        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);\r
     }\r
 \r
     return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL, NULL);\r
index f768ce8..5418006 100644 (file)
@@ -306,19 +306,23 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName
         code->internalDataPath = code->internalDataPathObj.string();
         env->ReleaseStringUTFChars(internalDataDir, dirStr);
     
-        dirStr = env->GetStringUTFChars(externalDataDir, NULL);
-        code->externalDataPathObj = dirStr;
+        if (externalDataDir != NULL) {
+            dirStr = env->GetStringUTFChars(externalDataDir, NULL);
+            code->externalDataPathObj = dirStr;
+            env->ReleaseStringUTFChars(externalDataDir, dirStr);
+        }
         code->externalDataPath = code->externalDataPathObj.string();
-        env->ReleaseStringUTFChars(externalDataDir, dirStr);
 
         code->sdkVersion = sdkVersion;
         
         code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
 
-        dirStr = env->GetStringUTFChars(obbDir, NULL);
-        code->obbPathObj = dirStr;
+        if (obbDir != NULL) {
+            dirStr = env->GetStringUTFChars(obbDir, NULL);
+            code->obbPathObj = dirStr;
+            env->ReleaseStringUTFChars(obbDir, dirStr);
+        }
         code->obbPath = code->obbPathObj.string();
-        env->ReleaseStringUTFChars(obbDir, dirStr);
 
         jbyte* rawSavedState = NULL;
         jsize rawSavedSize = 0;
index 27f93c0..9a1953f 100644 (file)
             <intent-filter android:priority="100">
                 <action android:name="android.intent.action.OPEN_DOCUMENT" />
                 <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.OPENABLE" />
                 <data android:mimeType="*/*" />
             </intent-filter>
             <intent-filter android:priority="100">
                 <action android:name="android.intent.action.CREATE_DOCUMENT" />
                 <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.OPENABLE" />
+                <data android:mimeType="*/*" />
+            </intent-filter>
+            <intent-filter android:priority="100">
+                <action android:name="android.intent.action.GET_CONTENT" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.OPENABLE" />
                 <data android:mimeType="*/*" />
             </intent-filter>
         </activity>
index 84f89b4..760f99b 100644 (file)
@@ -47,6 +47,7 @@
     <string name="root_type_service">Services</string>
     <string name="root_type_shortcut">Shortcuts</string>
     <string name="root_type_device">Devices</string>
+    <string name="root_type_apps">More apps</string>
 
     <string name="pref_advanced_devices">Display advanced devices</string>
     <string name="pref_file_size">Display file size</string>
index 5a6060a..e1b6a91 100644 (file)
@@ -144,7 +144,7 @@ public class DirectoryFragment extends Fragment {
                 final DisplayState state = getDisplayState(DirectoryFragment.this);
                 mFilter = new MimePredicate(state.acceptMimes);
 
-                final Uri contentsUri;
+                Uri contentsUri;
                 if (mType == TYPE_NORMAL) {
                     contentsUri = DocumentsContract.buildContentsUri(uri);
                 } else if (mType == TYPE_RECENT_OPEN) {
@@ -153,6 +153,10 @@ public class DirectoryFragment extends Fragment {
                     contentsUri = uri;
                 }
 
+                if (state.localOnly) {
+                    contentsUri = DocumentsContract.setLocalOnly(contentsUri);
+                }
+
                 final Comparator<Document> sortOrder;
                 if (state.sortOrder == DisplayState.SORT_ORDER_DATE || mType == TYPE_RECENT_OPEN) {
                     sortOrder = new Document.DateComparator();
index 94c2b61..98f9a4d 100644 (file)
@@ -26,6 +26,7 @@ import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.CancellationSignal;
+import android.provider.DocumentsContract.DocumentColumns;
 import android.util.Log;
 
 import com.android.documentsui.model.Document;
@@ -38,6 +39,7 @@ import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.LinkedList;
 import java.util.List;
 
 public class DirectoryLoader extends UriDerivativeLoader<List<Document>> {
@@ -46,6 +48,17 @@ public class DirectoryLoader extends UriDerivativeLoader<List<Document>> {
     private Predicate<Document> mFilter;
     private Comparator<Document> mSortOrder;
 
+    /**
+     * Stub result that represents an internal error.
+     */
+    public static class ExceptionResult extends LinkedList<Document> {
+        public final Exception e;
+
+        public ExceptionResult(Exception e) {
+            this.e = e;
+        }
+    }
+
     public DirectoryLoader(Context context, Uri uri, int type, Predicate<Document> filter,
             Comparator<Document> sortOrder) {
         super(context, uri);
@@ -56,11 +69,18 @@ public class DirectoryLoader extends UriDerivativeLoader<List<Document>> {
 
     @Override
     public List<Document> loadInBackground(Uri uri, CancellationSignal signal) {
+        try {
+            return loadInBackgroundInternal(uri, signal);
+        } catch (Exception e) {
+            return new ExceptionResult(e);
+        }
+    }
+
+    private List<Document> loadInBackgroundInternal(Uri uri, CancellationSignal signal) {
         final ArrayList<Document> result = Lists.newArrayList();
 
-        // TODO: send selection and sorting hints to backend
         final ContentResolver resolver = getContext().getContentResolver();
-        final Cursor cursor = resolver.query(uri, null, null, null, null, signal);
+        final Cursor cursor = resolver.query(uri, null, null, null, getQuerySortOrder(), signal);
         try {
             while (cursor != null && cursor.moveToNext()) {
                 Document doc = null;
@@ -94,4 +114,16 @@ public class DirectoryLoader extends UriDerivativeLoader<List<Document>> {
 
         return result;
     }
+
+    private String getQuerySortOrder() {
+        if (mSortOrder instanceof Document.DateComparator) {
+            return DocumentColumns.LAST_MODIFIED + " DESC";
+        } else if (mSortOrder instanceof Document.NameComparator) {
+            return DocumentColumns.DISPLAY_NAME + " ASC";
+        } else if (mSortOrder instanceof Document.SizeComparator) {
+            return DocumentColumns.SIZE + " DESC";
+        } else {
+            return null;
+        }
+    }
 }
index a536acb..89ba66e 100644 (file)
@@ -22,9 +22,11 @@ import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.content.ClipData;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Intent;
+import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.graphics.drawable.ColorDrawable;
 import android.net.Uri;
@@ -60,6 +62,7 @@ public class DocumentsActivity extends Activity {
 
     public static final int ACTION_OPEN = 1;
     public static final int ACTION_CREATE = 2;
+    public static final int ACTION_GET_CONTENT = 3;
 
     private int mAction;
 
@@ -84,11 +87,15 @@ public class DocumentsActivity extends Activity {
         final String action = intent.getAction();
         if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) {
             mAction = ACTION_OPEN;
-            mDisplayState.allowMultiple = intent.getBooleanExtra(
-                    Intent.EXTRA_ALLOW_MULTIPLE, false);
         } else if (Intent.ACTION_CREATE_DOCUMENT.equals(action)) {
             mAction = ACTION_CREATE;
-            mDisplayState.allowMultiple = false;
+        } else if (Intent.ACTION_GET_CONTENT.equals(action)) {
+            mAction = ACTION_GET_CONTENT;
+        }
+
+        if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
+            mDisplayState.allowMultiple = intent.getBooleanExtra(
+                    Intent.EXTRA_ALLOW_MULTIPLE, false);
         }
 
         if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
@@ -97,11 +104,7 @@ public class DocumentsActivity extends Activity {
             mDisplayState.acceptMimes = new String[] { intent.getType() };
         }
 
-        if (MimePredicate.mimeMatches("image/*", mDisplayState.acceptMimes)) {
-            mDisplayState.mode = DisplayState.MODE_GRID;
-        } else {
-            mDisplayState.mode = DisplayState.MODE_LIST;
-        }
+        mDisplayState.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
 
         setResult(Activity.RESULT_CANCELED);
         setContentView(R.layout.activity);
@@ -112,7 +115,14 @@ public class DocumentsActivity extends Activity {
             SaveFragment.show(getFragmentManager(), mimeType, title);
         }
 
-        RootsFragment.show(getFragmentManager());
+        if (mAction == ACTION_GET_CONTENT) {
+            final Intent moreApps = new Intent(getIntent());
+            moreApps.setComponent(null);
+            moreApps.setPackage(null);
+            RootsFragment.show(getFragmentManager(), moreApps);
+        } else {
+            RootsFragment.show(getFragmentManager(), null);
+        }
 
         mRootsContainer = findViewById(R.id.container_roots);
 
@@ -186,7 +196,7 @@ public class DocumentsActivity extends Activity {
             actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
             actionBar.setIcon(new ColorDrawable());
 
-            if (mAction == ACTION_OPEN) {
+            if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
                 actionBar.setTitle(R.string.title_open);
             } else if (mAction == ACTION_CREATE) {
                 actionBar.setTitle(R.string.title_save);
@@ -484,12 +494,21 @@ public class DocumentsActivity extends Activity {
         }
     }
 
+    public void onAppPicked(ResolveInfo info) {
+        final Intent intent = new Intent(getIntent());
+        intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+        intent.setComponent(new ComponentName(
+                info.activityInfo.applicationInfo.packageName, info.activityInfo.name));
+        startActivity(intent);
+        finish();
+    }
+
     public void onDocumentPicked(Document doc) {
         final FragmentManager fm = getFragmentManager();
         if (doc.isDirectory()) {
             mStack.push(doc);
             onCurrentDirectoryChanged();
-        } else if (mAction == ACTION_OPEN) {
+        } else if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
             // Explicit file picked, return
             onFinished(doc.uri);
         } else if (mAction == ACTION_CREATE) {
@@ -538,7 +557,7 @@ public class DocumentsActivity extends Activity {
             values.put(RecentsProvider.COL_PATH, rawStack);
             resolver.insert(RecentsProvider.buildRecentCreate(), values);
 
-        } else if (mAction == ACTION_OPEN) {
+        } else if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
             // Remember opened items
             for (Uri uri : uris) {
                 values.clear();
@@ -565,10 +584,13 @@ public class DocumentsActivity extends Activity {
             intent.setClipData(clipData);
         }
 
-        // TODO: omit WRITE and PERSIST for GET_CONTENT
-        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
-                | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION);
+        if (mAction == ACTION_GET_CONTENT) {
+            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        } else {
+            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                    | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION);
+        }
 
         setResult(Activity.RESULT_OK, intent);
         finish();
@@ -580,6 +602,7 @@ public class DocumentsActivity extends Activity {
         public int sortOrder = SORT_ORDER_NAME;
         public boolean allowMultiple = false;
         public boolean showSize = false;
+        public boolean localOnly = false;
 
         public static final int MODE_LIST = 0;
         public static final int MODE_GRID = 1;
index 5268c1d..dbcb039 100644 (file)
@@ -129,11 +129,11 @@ public class RecentsProvider extends ContentProvider {
         switch (sMatcher.match(uri)) {
             case URI_RECENT_OPEN: {
                 return db.query(TABLE_RECENT_OPEN, projection,
-                        buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, sortOrder);
+                        buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, null);
             }
             case URI_RECENT_CREATE: {
                 return db.query(TABLE_RECENT_CREATE, projection,
-                        buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, sortOrder);
+                        buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, null);
             }
             case URI_RESUME: {
                 final String packageName = uri.getPathSegments().get(1);
index b26db3b..ceab8fc 100644 (file)
@@ -95,19 +95,24 @@ public class RootsCache {
 
                 sProviders.put(info.providerInfo.authority, info);
 
-                // TODO: remove deprecated customRoots flag
-                // TODO: populate roots on background thread, and cache results
-                final Uri uri = DocumentsContract.buildRootsUri(providerInfo.authority);
-                final Cursor cursor = context.getContentResolver()
-                        .query(uri, null, null, null, null);
                 try {
-                    while (cursor.moveToNext()) {
-                        final Root root = Root.fromCursor(context, info, cursor);
-                        sRoots.put(Pair.create(info.providerInfo.authority, root.rootId), root);
-                        sRootsList.add(root);
+                    // TODO: remove deprecated customRoots flag
+                    // TODO: populate roots on background thread, and cache results
+                    final Uri uri = DocumentsContract.buildRootsUri(providerInfo.authority);
+                    final Cursor cursor = context.getContentResolver()
+                            .query(uri, null, null, null, null);
+                    try {
+                        while (cursor.moveToNext()) {
+                            final Root root = Root.fromCursor(context, info, cursor);
+                            sRoots.put(Pair.create(info.providerInfo.authority, root.rootId), root);
+                            sRootsList.add(root);
+                        }
+                    } finally {
+                        cursor.close();
                     }
-                } finally {
-                    cursor.close();
+                } catch (Exception e) {
+                    Log.w(TAG, "Failed to load some roots from " + info.providerInfo.authority
+                            + ": " + e);
                 }
             }
         }
index 427ad42..e32414b 100644 (file)
@@ -22,6 +22,9 @@ import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.provider.DocumentsContract;
 import android.text.format.Formatter;
@@ -41,6 +44,8 @@ import com.android.documentsui.model.Root;
 import com.android.documentsui.model.Root.RootComparator;
 
 import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
 
 /**
  * Display list of known storage backend roots.
@@ -50,8 +55,14 @@ public class RootsFragment extends Fragment {
     private ListView mList;
     private SectionedRootsAdapter mAdapter;
 
-    public static void show(FragmentManager fm) {
+    private static final String EXTRA_INCLUDE_APPS = "includeApps";
+
+    public static void show(FragmentManager fm, Intent includeApps) {
+        final Bundle args = new Bundle();
+        args.putParcelable(EXTRA_INCLUDE_APPS, includeApps);
+
         final RootsFragment fragment = new RootsFragment();
+        fragment.setArguments(args);
 
         final FragmentTransaction ft = fm.beginTransaction();
         ft.replace(R.id.container_roots, fragment);
@@ -69,11 +80,11 @@ public class RootsFragment extends Fragment {
 
         final View view = inflater.inflate(R.layout.fragment_roots, container, false);
         mList = (ListView) view.findViewById(android.R.id.list);
-
-        mAdapter = new SectionedRootsAdapter(context, RootsCache.getRoots(context));
-        mList.setAdapter(mAdapter);
         mList.setOnItemClickListener(mItemListener);
 
+        final Intent includeApps = getArguments().getParcelable(EXTRA_INCLUDE_APPS);
+        mAdapter = new SectionedRootsAdapter(context, RootsCache.getRoots(context), includeApps);
+
         return view;
     }
 
@@ -82,18 +93,26 @@ public class RootsFragment extends Fragment {
         super.onStart();
 
         final Context context = getActivity();
-        mAdapter.setShowAdvanced(SettingsActivity.getDisplayAdvancedDevices(context));
+        mAdapter.updateVisible(SettingsActivity.getDisplayAdvancedDevices(context));
+        mList.setAdapter(mAdapter);
     }
 
     private OnItemClickListener mItemListener = new OnItemClickListener() {
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-            final Root root = (Root) mAdapter.getItem(position);
-            ((DocumentsActivity) getActivity()).onRootPicked(root, true);
+            final DocumentsActivity activity = DocumentsActivity.get(RootsFragment.this);
+            final Object item = mAdapter.getItem(position);
+            if (item instanceof Root) {
+                activity.onRootPicked((Root) item, true);
+            } else if (item instanceof ResolveInfo) {
+                activity.onAppPicked((ResolveInfo) item);
+            } else {
+                throw new IllegalStateException("Unknown root: " + item);
+            }
         }
     };
 
-    public static class RootsAdapter extends ArrayAdapter<Root> implements SectionAdapter {
+    private static class RootsAdapter extends ArrayAdapter<Root> implements SectionAdapter {
         private int mHeaderId;
 
         public RootsAdapter(Context context, int headerId) {
@@ -148,17 +167,61 @@ public class RootsFragment extends Fragment {
         }
     }
 
-    public static class SectionedRootsAdapter extends SectionedListAdapter {
+    private static class AppsAdapter extends ArrayAdapter<ResolveInfo> implements SectionAdapter {
+        public AppsAdapter(Context context) {
+            super(context, 0);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final Context context = parent.getContext();
+            final PackageManager pm = context.getPackageManager();
+            if (convertView == null) {
+                convertView = LayoutInflater.from(context)
+                        .inflate(R.layout.item_root, parent, false);
+            }
+
+            final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
+            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+            final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
+
+            final ResolveInfo info = getItem(position);
+            icon.setImageDrawable(info.loadIcon(pm));
+            title.setText(info.loadLabel(pm));
+
+            // TODO: match existing summary behavior from disambig dialog
+            summary.setVisibility(View.GONE);
+
+            return convertView;
+        }
+
+        @Override
+        public View getHeaderView(View convertView, ViewGroup parent) {
+            if (convertView == null) {
+                convertView = LayoutInflater.from(parent.getContext())
+                        .inflate(R.layout.item_root_header, parent, false);
+            }
+
+            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+            title.setText(R.string.root_type_apps);
+
+            return convertView;
+        }
+    }
+
+    private static class SectionedRootsAdapter extends SectionedListAdapter {
         private final RootsAdapter mServices;
         private final RootsAdapter mShortcuts;
         private final RootsAdapter mDevices;
         private final RootsAdapter mDevicesAdvanced;
+        private final AppsAdapter mApps;
 
-        public SectionedRootsAdapter(Context context, Collection<Root> roots) {
+        public SectionedRootsAdapter(Context context, Collection<Root> roots, Intent includeApps) {
             mServices = new RootsAdapter(context, R.string.root_type_service);
             mShortcuts = new RootsAdapter(context, R.string.root_type_shortcut);
             mDevices = new RootsAdapter(context, R.string.root_type_device);
             mDevicesAdvanced = new RootsAdapter(context, R.string.root_type_device);
+            mApps = new AppsAdapter(context);
 
             for (Root root : roots) {
                 Log.d(TAG, "Found rootType=" + root.rootType);
@@ -179,6 +242,19 @@ public class RootsFragment extends Fragment {
                 }
             }
 
+            if (includeApps != null) {
+                final PackageManager pm = context.getPackageManager();
+                final List<ResolveInfo> infos = pm.queryIntentActivities(
+                        includeApps, PackageManager.MATCH_DEFAULT_ONLY);
+
+                // Omit ourselves from the list
+                for (ResolveInfo info : infos) {
+                    if (!context.getPackageName().equals(info.activityInfo.packageName)) {
+                        mApps.add(info);
+                    }
+                }
+            }
+
             final RootComparator comp = new RootComparator();
             mServices.sort(comp);
             mShortcuts.sort(comp);
@@ -186,7 +262,7 @@ public class RootsFragment extends Fragment {
             mDevicesAdvanced.sort(comp);
         }
 
-        public void setShowAdvanced(boolean showAdvanced) {
+        public void updateVisible(boolean showAdvanced) {
             clearSections();
             if (mServices.getCount() > 0) {
                 addSection(mServices);
@@ -199,6 +275,10 @@ public class RootsFragment extends Fragment {
             if (devices.getCount() > 0) {
                 addSection(devices);
             }
+
+            if (mApps.getCount() > 0) {
+                addSection(mApps);
+            }
         }
     }
 }
index aacce65..088e3fa 100644 (file)
@@ -18,6 +18,7 @@ package com.android.documentsui;
 
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.ListAdapter;
 
@@ -41,6 +42,11 @@ public class SectionedListAdapter extends BaseAdapter {
         notifyDataSetChanged();
     }
 
+    /**
+     * After mutating sections, you <em>must</em>
+     * {@link AdapterView#setAdapter(android.widget.Adapter)} to correctly
+     * recount view types.
+     */
     public void addSection(SectionAdapter adapter) {
         mSections.add(adapter);
         notifyDataSetChanged();
@@ -117,7 +123,7 @@ public class SectionedListAdapter extends BaseAdapter {
             if (position == 0) {
                 return false;
             } else if (position < sectionSize) {
-                return section.isEnabled(position);
+                return section.isEnabled(position - 1);
             }
 
             // Otherwise jump into next section
index a086a43..f6548e8 100644 (file)
@@ -60,6 +60,7 @@ public class TestActivity extends Activity {
             @Override
             public void onClick(View v) {
                 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+                intent.addCategory(Intent.CATEGORY_OPENABLE);
                 intent.setType("*/*");
                 if (multiple.isChecked()) {
                     intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
@@ -75,6 +76,7 @@ public class TestActivity extends Activity {
             @Override
             public void onClick(View v) {
                 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+                intent.addCategory(Intent.CATEGORY_OPENABLE);
                 intent.setType("image/*");
                 if (multiple.isChecked()) {
                     intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
@@ -90,6 +92,7 @@ public class TestActivity extends Activity {
             @Override
             public void onClick(View v) {
                 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+                intent.addCategory(Intent.CATEGORY_OPENABLE);
                 intent.setType("*/*");
                 intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {
                         "text/plain", "application/msword" });
@@ -107,6 +110,7 @@ public class TestActivity extends Activity {
             @Override
             public void onClick(View v) {
                 Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+                intent.addCategory(Intent.CATEGORY_OPENABLE);
                 intent.setType("text/plain");
                 intent.putExtra(Intent.EXTRA_TITLE, "foobar.txt");
                 startActivityForResult(intent, 42);
@@ -114,6 +118,22 @@ public class TestActivity extends Activity {
         });
         view.addView(button);
 
+        button = new Button(context);
+        button.setText("GET_CONTENT */*");
+        button.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+                intent.addCategory(Intent.CATEGORY_OPENABLE);
+                intent.setType("*/*");
+                if (multiple.isChecked()) {
+                    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+                }
+                startActivityForResult(Intent.createChooser(intent, "Kittens!"), 42);
+            }
+        });
+        view.addView(button);
+
         mResult = new TextView(context);
         view.addView(mResult);
 
@@ -131,7 +151,7 @@ public class TestActivity extends Activity {
                 is = getContentResolver().openInputStream(uri);
                 final int length = Streams.readFullyNoClose(is).length;
                 Log.d(TAG, "read length=" + length);
-            } catch (IOException e) {
+            } catch (Exception e) {
                 Log.w(TAG, "Failed to read " + uri, e);
             } finally {
                 IoUtils.closeQuietly(is);
index 74b14b0..199c65a 100644 (file)
@@ -21,16 +21,19 @@ import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.util.Log;
 import android.view.View;
 
 import com.android.systemui.R;
 
 public class BarTransitions {
+    private static final boolean DEBUG = false;
 
     public static final int MODE_NORMAL = 0;
     public static final int MODE_TRANSIENT = 1;
     public static final int MODE_TRANSPARENT = 2;
 
+    private final String mTag;
     private final View mTarget;
     private final Drawable mOpaque;
     private final Drawable mTransient;
@@ -39,6 +42,7 @@ public class BarTransitions {
     private int mMode;
 
     public BarTransitions(Context context, View target, Drawable transparent) {
+        mTag = "BarTransitions." + target.getClass().getSimpleName();
         mTarget = target;
         final Resources res = context.getResources();
         mOpaque = new ColorDrawable(res.getColor(R.drawable.status_bar_background));
@@ -56,9 +60,17 @@ public class BarTransitions {
     public void transitionTo(int mode) {
         mMode = mode;
         if (!ActivityManager.isHighEndGfx()) return;
+        if (DEBUG) Log.d(mTag, "transitionTo " + modeToString(mode));
         Drawable background = mode == MODE_TRANSIENT ? mTransient
                 : mode == MODE_TRANSPARENT ? mTransparent
                 : mOpaque;
         mTarget.setBackground(background);
     }
+
+    public static String modeToString(int mode) {
+        if (mode == MODE_NORMAL) return "MODE_NORMAL";
+        if (mode == MODE_TRANSIENT) return "MODE_TRANSIENT";
+        if (mode == MODE_TRANSPARENT) return "MODE_TRANSPARENT";
+        throw new IllegalArgumentException("Unknown mode " + mode);
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/BarController.java b/policy/src/com/android/internal/policy/impl/BarController.java
new file mode 100644 (file)
index 0000000..fb76e20
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.policy.impl;
+
+import android.app.StatusBarManager;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+import android.view.View;
+import android.view.WindowManagerPolicy.WindowState;
+
+import com.android.internal.statusbar.IStatusBarService;
+
+import java.io.PrintWriter;
+
+/**
+ * Controls state/behavior specific to a system bar window.
+ */
+public class BarController {
+    private static final boolean DEBUG = false;
+
+    private static final int TRANSIENT_BAR_NONE = 0;
+    private static final int TRANSIENT_BAR_SHOWING = 1;
+    private static final int TRANSIENT_BAR_HIDING = 2;
+
+    private final String mTag;
+    private final int mTransientFlag;
+    private final int mStatusBarManagerId;
+    private final Handler mHandler;
+    private final Object mServiceAquireLock = new Object();
+    private IStatusBarService mStatusBarService;
+
+    private WindowState mWin;
+    private int mTransientBarState;
+    private boolean mPendingShow;
+
+    public BarController(String tag, int transientFlag, int statusBarManagerId) {
+        mTag = "BarController." + tag;
+        mTransientFlag = transientFlag;
+        mStatusBarManagerId = statusBarManagerId;
+        mHandler = new Handler();
+    }
+
+    public void setWindow(WindowState win) {
+        mWin = win;
+    }
+
+    public void showTransient() {
+        if (mWin != null) {
+            setTransientBarState(TRANSIENT_BAR_SHOWING);
+        }
+    }
+
+    public boolean isTransientShowing() {
+        return mTransientBarState == TRANSIENT_BAR_SHOWING;
+    }
+
+    public void adjustSystemUiVisibilityLw(int visibility) {
+        if (mWin != null && mTransientBarState == TRANSIENT_BAR_SHOWING &&
+                (visibility & mTransientFlag) == 0) {
+            setTransientBarState(TRANSIENT_BAR_HIDING);
+            setBarShowingLw(false);
+        }
+    }
+
+    public boolean setBarShowingLw(final boolean show) {
+        if (mWin == null) return false;
+
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    IStatusBarService statusbar = getStatusBarService();
+                    if (statusbar != null) {
+                        statusbar.setWindowState(mStatusBarManagerId, show
+                                ? StatusBarManager.WINDOW_STATE_SHOWING
+                                : StatusBarManager.WINDOW_STATE_HIDING);
+                    }
+                } catch (RemoteException e) {
+                    // re-acquire status bar service next time it is needed.
+                    mStatusBarService = null;
+                }
+            }
+        });
+        if (show && mTransientBarState == TRANSIENT_BAR_HIDING) {
+            mPendingShow = true;
+            return false;
+        }
+        return show ? mWin.showLw(true) : mWin.hideLw(true);
+    }
+
+    public boolean checkHiddenLw() {
+        if (mWin != null && mTransientBarState == TRANSIENT_BAR_HIDING && !mWin.isVisibleLw()) {
+            // Finished animating out, clean up and reset style
+            setTransientBarState(TRANSIENT_BAR_NONE);
+            if (mPendingShow) {
+                setBarShowingLw(true);
+                mPendingShow = false;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public boolean checkShowTransientBarLw() {
+        if (mTransientBarState == TRANSIENT_BAR_SHOWING) {
+            if (DEBUG) Slog.d(mTag, "Not showing transient bar, already shown");
+            return false;
+        } else if (mWin == null) {
+            if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar doesn't exist");
+            return false;
+        } else if (mWin.isDisplayedLw()) {
+            if (DEBUG) Slog.d(mTag, "Not showing transient bar, bar already visible");
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    public int updateVisibilityLw(boolean allowed, int oldVis, int vis) {
+        if (mWin == null) return vis;
+
+        if (mTransientBarState == TRANSIENT_BAR_SHOWING) { // transient bar requested
+            if (allowed) {
+                vis |= mTransientFlag;
+                if ((oldVis & mTransientFlag) == 0) {
+                    setBarShowingLw(true);
+                }
+            } else {
+                setTransientBarState(TRANSIENT_BAR_NONE);  // request denied
+            }
+        }
+        if (mTransientBarState != TRANSIENT_BAR_NONE) {
+            vis |= mTransientFlag;  // ignore clear requests until transition completes
+            vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;  // never show transient bars in low profile
+        }
+        return vis;
+    }
+
+    private void setTransientBarState(int state) {
+        if (mWin != null && state != mTransientBarState) {
+            mTransientBarState = state;
+            if (DEBUG) Slog.d(mTag, "New state: " + transientBarStateToString(state));
+        }
+    }
+
+    private IStatusBarService getStatusBarService() {
+        synchronized (mServiceAquireLock) {
+            if (mStatusBarService == null) {
+                mStatusBarService = IStatusBarService.Stub.asInterface(
+                        ServiceManager.getService("statusbar"));
+            }
+            return mStatusBarService;
+        }
+    }
+
+    private static String transientBarStateToString(int state) {
+        if (state == TRANSIENT_BAR_HIDING) return "TRANSIENT_BAR_HIDING";
+        if (state == TRANSIENT_BAR_SHOWING) return "TRANSIENT_BAR_SHOWING";
+        if (state == TRANSIENT_BAR_NONE) return "TRANSIENT_BAR_NONE";
+        throw new IllegalArgumentException("Unknown state " + state);
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        if (mWin != null) {
+            pw.print(prefix); pw.print(mTag); pw.print(' ');
+            pw.print("mTransientBar"); pw.print('=');
+            pw.println(transientBarStateToString(mTransientBarState));
+        }
+    }
+}
index 22b5f03..11e33dc 100644 (file)
@@ -553,11 +553,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
     }
     MyOrientationListener mOrientationListener;
 
-    private static final int TRANSIENT_BAR_NONE = 0;
-    private static final int TRANSIENT_BAR_SHOWING = 1;
-    private static final int TRANSIENT_BAR_HIDING = 2;
-    private int mStatusTransientBar;
-    private int mNavigationTransientBar;
+    private final BarController mStatusBarController = new BarController("StatusBar",
+            View.STATUS_BAR_TRANSIENT, StatusBarManager.WINDOW_STATUS_BAR);
+    private final BarController mNavigationBarController = new BarController("NavigationBar",
+            View.NAVIGATION_BAR_TRANSIENT, StatusBarManager.WINDOW_NAVIGATION_BAR);
     private TransientNavigationConfirmation mTransientNavigationConfirmation;
 
     private SystemGesturesPointerEventListener mSystemGestures;
@@ -1716,6 +1715,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                     }
                 }
                 mStatusBar = win;
+                mStatusBarController.setWindow(win);
                 break;
             case TYPE_NAVIGATION_BAR:
                 mContext.enforceCallingOrSelfPermission(
@@ -1727,6 +1727,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                     }
                 }
                 mNavigationBar = win;
+                mNavigationBarController.setWindow(win);
                 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
                 break;
             case TYPE_NAVIGATION_BAR_PANEL:
@@ -1765,6 +1766,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
     public void removeWindowLw(WindowState win) {
         if (mStatusBar == win) {
             mStatusBar = null;
+            mStatusBarController.setWindow(null);
         } else if (mKeyguard == win) {
             Log.v(TAG, "Removing keyguard window (Did it crash?)");
             mKeyguard = null;
@@ -1774,6 +1776,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
             mKeyguardScrim = null;
         } if (mNavigationBar == win) {
             mNavigationBar = null;
+            mNavigationBarController.setWindow(null);
         }
     }
 
@@ -2548,16 +2551,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
 
     @Override
     public int adjustSystemUiVisibilityLw(int visibility) {
-        if (mStatusBar != null && mStatusTransientBar == TRANSIENT_BAR_SHOWING &&
-                0 == (visibility & View.STATUS_BAR_TRANSIENT)) {
-            mStatusTransientBar = TRANSIENT_BAR_HIDING;
-            setBarShowingLw(mStatusBar, false);
-        }
-        if (mNavigationBar != null && mNavigationTransientBar == TRANSIENT_BAR_SHOWING &&
-                0 == (visibility & View.NAVIGATION_BAR_TRANSIENT)) {
-            mNavigationTransientBar = TRANSIENT_BAR_HIDING;
-            setBarShowingLw(mNavigationBar, false);
-        }
+        mStatusBarController.adjustSystemUiVisibilityLw(visibility);
+        mNavigationBarController.adjustSystemUiVisibilityLw(visibility);
+
         // Reset any bits in mForceClearingStatusBarVisibility that
         // are now clear.
         mResettingSystemUiFlags &= visibility;
@@ -2714,7 +2710,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
 
             boolean updateSysUiVisibility = false;
             if (mNavigationBar != null) {
-                boolean transientNavBarShowing = mNavigationTransientBar == TRANSIENT_BAR_SHOWING;
+                boolean transientNavBarShowing = mNavigationBarController.isTransientShowing();
                 // Force the navigation bar to its appropriate place and
                 // size.  We need to do this directly, instead of relying on
                 // it to bubble up from the nav bar, because this needs to
@@ -2727,15 +2723,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                     mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom);
                     mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
                     if (transientNavBarShowing || navTransparent) {
-                        setBarShowingLw(mNavigationBar, true);
+                        mNavigationBarController.setBarShowingLw(true);
                     } else if (navVisible) {
-                        setBarShowingLw(mNavigationBar, true);
+                        mNavigationBarController.setBarShowingLw(true);
                         mDockBottom = mTmpNavigationFrame.top;
                         mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop;
                         mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop;
                     } else {
                         // We currently want to hide the navigation UI.
-                        setBarShowingLw(mNavigationBar, false);
+                        mNavigationBarController.setBarShowingLw(false);
                     }
                     if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw()) {
                         // If the opaque nav bar is currently requested to be visible,
@@ -2750,15 +2746,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                     mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
                     mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
                     if (transientNavBarShowing || navTransparent) {
-                        setBarShowingLw(mNavigationBar, true);
+                        mNavigationBarController.setBarShowingLw(true);
                     } else if (navVisible) {
-                        setBarShowingLw(mNavigationBar, true);
+                        mNavigationBarController.setBarShowingLw(true);
                         mDockRight = mTmpNavigationFrame.left;
                         mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft;
                         mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft;
                     } else {
                         // We currently want to hide the navigation UI.
-                        setBarShowingLw(mNavigationBar, false);
+                        mNavigationBarController.setBarShowingLw(false);
                     }
                     if (navVisible && !navTransparent && !mNavigationBar.isAnimatingLw()) {
                         // If the nav bar is currently requested to be visible,
@@ -2778,9 +2774,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
                         mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame);
                 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
-                if (mNavigationTransientBar == TRANSIENT_BAR_HIDING && !mNavigationBar.isVisibleLw()) {
-                    // Finished animating out, clean up and reset alpha
-                    mNavigationTransientBar = TRANSIENT_BAR_NONE;
+                if (mNavigationBarController.checkHiddenLw()) {
                     updateSysUiVisibility = true;
                 }
             }
@@ -2838,10 +2832,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                     // we can tell the app that it is covered by it.
                     mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
                 }
-
-                if (mStatusTransientBar == TRANSIENT_BAR_HIDING && !mStatusBar.isVisibleLw()) {
-                    // Finished animating out, clean up and reset alpha
-                    mStatusTransientBar = TRANSIENT_BAR_NONE;
+                if (mStatusBarController.checkHiddenLw()) {
                     updateSysUiVisibility = true;
                 }
             }
@@ -3410,7 +3401,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                     + " top=" + mTopFullscreenOpaqueWindowState);
             if (mForceStatusBar || mForceStatusBarFromKeyguard) {
                 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced");
-                if (setBarShowingLw(mStatusBar, true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
+                if (mStatusBarController.setBarShowingLw(true)) {
+                    changes |= FINISH_LAYOUT_REDO_LAYOUT;
+                }
             } else if (mTopFullscreenOpaqueWindowState != null) {
                 if (localLOGV) {
                     Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
@@ -3424,20 +3417,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                 // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window
                 // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
                 // case though.
-                if (mStatusTransientBar == TRANSIENT_BAR_SHOWING) {
-                    if (setBarShowingLw(mStatusBar, true)) {
+                if (mStatusBarController.isTransientShowing()) {
+                    if (mStatusBarController.setBarShowingLw(true)) {
                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
                     }
                 } else if (topIsFullscreen) {
                     if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar");
-                    if (setBarShowingLw(mStatusBar, false)) {
+                    if (mStatusBarController.setBarShowingLw(false)) {
                         changes |= FINISH_LAYOUT_REDO_LAYOUT;
                     } else {
                         if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding");
                     }
                 } else {
                     if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen");
-                    if (setBarShowingLw(mStatusBar, true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
+                    if (mStatusBarController.setBarShowingLw(true)) {
+                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
+                    }
                 }
             }
         }
@@ -3882,7 +3877,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
             case KeyEvent.KEYCODE_POWER: {
                 result &= ~ACTION_PASS_TO_USER;
                 if (down) {
-                    if (isScreenOn && isNavigationBarTransient(mLastSystemUiFlags)) {
+                    if (isScreenOn && isTransientNavigationAllowed(mLastSystemUiFlags)) {
                         mTransientNavigationConfirmation.unconfirmLastPackage();
                     }
                     if (isScreenOn && !mPowerKeyTriggered
@@ -4153,36 +4148,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
 
     private void requestTransientBars(WindowState swipeTarget) {
         synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
-            boolean sb = checkShowTransientBar("status", mStatusTransientBar, mStatusBar);
-            boolean nb = checkShowTransientBar("nav", mNavigationTransientBar, mNavigationBar);
+            boolean sb = mStatusBarController.checkShowTransientBarLw();
+            boolean nb = mNavigationBarController.checkShowTransientBarLw();
             if (sb || nb) {
                 WindowState barTarget = sb ? mStatusBar : mNavigationBar;
                 if (sb ^ nb && barTarget != swipeTarget) {
                     if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target");
                     return;
                 }
-                mStatusTransientBar = sb ? TRANSIENT_BAR_SHOWING : mStatusTransientBar;
-                mNavigationTransientBar = nb ? TRANSIENT_BAR_SHOWING : mNavigationTransientBar;
+                if (sb) mStatusBarController.showTransient();
+                if (nb) mNavigationBarController.showTransient();
                 updateSystemUiVisibilityLw();
             }
         }
     }
 
-    private boolean checkShowTransientBar(String tag, int transientBar, WindowState win) {
-        if (transientBar == TRANSIENT_BAR_SHOWING) {
-            if (DEBUG) Slog.d(TAG, "Not showing " + tag + " transient bar, already shown");
-            return false;
-        } else if (win == null) {
-            if (DEBUG) Slog.d(TAG, "Not showing " + tag + " transient bar, bar doesn't exist");
-            return false;
-        } else if (win.isDisplayedLw()) {
-            if (DEBUG) Slog.d(TAG, "Not showing " + tag + " transient bar, bar already visible");
-            return false;
-        } else {
-            return true;
-        }
-    }
-
     @Override
     public void screenTurnedOff(int why) {
         EventLog.writeEvent(70000, 0);
@@ -5057,106 +5037,62 @@ public class PhoneWindowManager implements WindowManagerPolicy {
         if (ImmersiveModeTesting.enabled) {
             vis = ImmersiveModeTesting.applyForced(mFocusedWindow, vis);
         }
+
+        // prevent status bar interaction from clearing certain flags
         boolean statusBarHasFocus = mFocusedWindow.getAttrs().type == TYPE_STATUS_BAR;
         if (statusBarHasFocus) {
-            // prevent status bar interaction from clearing certain flags
             int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                     | View.SYSTEM_UI_FLAG_ALLOW_TRANSIENT;
             vis = (vis & ~flags) | (mLastSystemUiFlags & flags);
         }
-        if (mStatusTransientBar == TRANSIENT_BAR_SHOWING) {
-            // status transient bar requested
-            boolean transientAllowed =
-                    (vis & View.SYSTEM_UI_FLAG_ALLOW_TRANSIENT) != 0;
-            boolean hideStatusBarWM =
-                    (mFocusedWindow.getAttrs().flags
-                            & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
-            boolean hideStatusBarSysui =
-                    (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
-
-            boolean transientStatusBarAllowed =
-                    hideStatusBarWM
-                    || (hideStatusBarSysui && transientAllowed)
-                    || statusBarHasFocus;
-
-            if (mStatusBar == null || !transientStatusBarAllowed) {
-                mStatusTransientBar = TRANSIENT_BAR_NONE;
-                if (mStatusBar != null && hideStatusBarSysui) {
-                    // clear the clearable flags instead
-                    int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
-                    if (newVal != mResettingSystemUiFlags) {
-                        mResettingSystemUiFlags = newVal;
-                        mWindowManagerFuncs.reevaluateStatusBarVisibility();
-                    }
-                }
-            } else {
-                // show status transient bar
-                vis |= View.STATUS_BAR_TRANSIENT;
-                if ((mLastSystemUiFlags & View.STATUS_BAR_TRANSIENT) == 0) {
-                    vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
-                    setBarShowingLw(mStatusBar, true);
-                }
+
+        // update status bar
+        boolean transientAllowed =
+                (vis & View.SYSTEM_UI_FLAG_ALLOW_TRANSIENT) != 0;
+        boolean hideStatusBarWM =
+                (mFocusedWindow.getAttrs().flags
+                        & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
+        boolean hideStatusBarSysui =
+                (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
+
+        boolean transientStatusBarAllowed =
+                mStatusBar != null && (
+                hideStatusBarWM
+                || (hideStatusBarSysui && transientAllowed)
+                || statusBarHasFocus);
+
+        if (mStatusBarController.isTransientShowing()
+                && !transientStatusBarAllowed && hideStatusBarSysui) {
+            // clear the clearable flags instead
+            int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
+            if (newVal != mResettingSystemUiFlags) {
+                mResettingSystemUiFlags = newVal;
+                mWindowManagerFuncs.reevaluateStatusBarVisibility();
             }
         }
-        boolean oldTransientNav = isNavigationBarTransient(oldVis);
-        boolean isTransientNav = isNavigationBarTransient(vis);
+
+        vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
+
+        // update navigation bar
+        boolean oldTransientNav = isTransientNavigationAllowed(oldVis);
+        boolean isTransientNav = isTransientNavigationAllowed(vis);
         if (mFocusedWindow != null && oldTransientNav != isTransientNav) {
             final int uid = getCurrentUserId();
             final String pkg = mFocusedWindow.getOwningPackage();
             mTransientNavigationConfirmation.transientNavigationChanged(uid, pkg, isTransientNav);
         }
-        if (mNavigationTransientBar == TRANSIENT_BAR_SHOWING) {
-            // navigation transient bar requested
-            if (!isTransientNav) {
-                mNavigationTransientBar = TRANSIENT_BAR_NONE;
-            } else {
-                // show navigation transient bar
-                vis |= View.NAVIGATION_BAR_TRANSIENT;
-                if ((mLastSystemUiFlags & View.NAVIGATION_BAR_TRANSIENT) == 0) {
-                    setBarShowingLw(mNavigationBar, true);
-                }
-            }
-        }
-        if (mStatusTransientBar != TRANSIENT_BAR_NONE
-                || mNavigationTransientBar != TRANSIENT_BAR_NONE) {
-            vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
-        }
+        vis = mNavigationBarController.updateVisibilityLw(isTransientNav, oldVis, vis);
+
         return vis;
     }
 
-    private boolean isNavigationBarTransient(int vis) {
+    private boolean isTransientNavigationAllowed(int vis) {
         return mNavigationBar != null
                 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
                 && (vis & View.SYSTEM_UI_FLAG_ALLOW_TRANSIENT) != 0;
     }
 
-    private boolean setBarShowingLw(WindowState win, final boolean show) {
-        final int window =
-                  win == mStatusBar ? StatusBarManager.WINDOW_STATUS_BAR
-                : win == mNavigationBar ? StatusBarManager.WINDOW_NAVIGATION_BAR
-                : 0;
-        if (window != 0) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        IStatusBarService statusbar = getStatusBarService();
-                        if (statusbar != null) {
-                            statusbar.setWindowState(window, show
-                                    ? StatusBarManager.WINDOW_STATE_SHOWING
-                                    : StatusBarManager.WINDOW_STATE_HIDING);
-                        }
-                    } catch (RemoteException e) {
-                        // re-acquire status bar service next time it is needed.
-                        mStatusBarService = null;
-                    }
-                }
-            });
-        }
-        return show ? win.showLw(true) : win.hideLw(true);
-    }
-
     // Temporary helper that allows testing immersive mode on existing apps
     // TODO remove
     private static final class ImmersiveModeTesting {
@@ -5417,18 +5353,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
         pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation);
                 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock);
         pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation);
-        dumpTransient(pw, prefix,
-                mStatusBar, "mStatusTransientBar", mStatusTransientBar);
-        dumpTransient(pw, prefix,
-                mNavigationBar, "mNavigationTransientBar", mNavigationTransientBar);
-    }
-
-    private void dumpTransient(PrintWriter pw, String pre, WindowState win, String var, int val) {
-        if (win != null) {
-            pw.print(pre); pw.print(var); pw.print('=');
-            pw.println(val == TRANSIENT_BAR_HIDING ? "HIDING"
-                     : val == TRANSIENT_BAR_SHOWING ? "SHOWING"
-                     : "NONE");
-        }
+        mStatusBarController.dump(pw, prefix);
+        mNavigationBarController.dump(pw, prefix);
     }
 }
index 98daaf5..a8bb636 100644 (file)
@@ -1285,6 +1285,9 @@ protected:
             if (haveSizeBias) {
                 *outSize += sizeBias;
             }
+            if (*outSize < 0) {
+                *outSize = 0;
+            }
         }
     } mCalibration;
 
index f6d5c98..a80238b 100644 (file)
@@ -506,13 +506,14 @@ public class WifiMonitor {
                     Log.d(TAG, "Event [" + eventStr + "]");
                 }
 
+                String iface = "p2p0";
                 WifiMonitor m = null;
                 mStateMachine = null;
 
                 if (eventStr.startsWith("IFNAME=")) {
                     int space = eventStr.indexOf(' ');
                     if (space != -1) {
-                        String iface = eventStr.substring(7,space);
+                        iface = eventStr.substring(7,space);
                         m = mWifiMonitorSingleton.getMonitor(iface);
                         if (m == null && iface.startsWith("p2p-")) {
                             // p2p interfaces are created dynamically, but we have
@@ -520,20 +521,20 @@ public class WifiMonitor {
                             // for it explicitly, and send messages there ..
                             m = mWifiMonitorSingleton.getMonitor("p2p0");
                         }
-                        if (m != null) {
-                            if (m.mMonitoring) {
-                                mStateMachine = m.mWifiStateMachine;
-                                eventStr = eventStr.substring(space + 1);
-                            }
-                            else {
-                                if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface +
-                                        ") is stopped");
-                                continue;
-                            }
-                        }
-                        else {
-                            eventStr = eventStr.substring(space + 1);
-                        }
+                        eventStr = eventStr.substring(space + 1);
+                    }
+                } else {
+                    // events without prefix belong to p2p0 monitor
+                    m = mWifiMonitorSingleton.getMonitor("p2p0");
+                }
+
+                if (m != null) {
+                    if (m.mMonitoring) {
+                        mStateMachine = m.mWifiStateMachine;
+                    } else {
+                        if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface +
+                                            ") is stopped");
+                        continue;
                     }
                 }