diff options
-rw-r--r-- | api/current.xml | 113 | ||||
-rw-r--r-- | camera/libcameraservice/CameraService.cpp | 11 | ||||
-rw-r--r-- | camera/libcameraservice/CameraService.h | 4 | ||||
-rw-r--r-- | core/java/android/content/ContentProvider.java | 136 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageParser.java | 98 | ||||
-rw-r--r-- | core/java/android/content/pm/PathPermission.java | 68 | ||||
-rw-r--r-- | core/java/android/content/pm/ProviderInfo.java | 12 | ||||
-rw-r--r-- | core/java/android/speech/tts/TextToSpeech.java | 1 | ||||
-rw-r--r-- | core/jni/android_hardware_Camera.cpp | 7 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 23 | ||||
-rw-r--r-- | core/res/res/values/attrs_manifest.xml | 14 | ||||
-rw-r--r-- | include/ui/Camera.h | 3 | ||||
-rw-r--r-- | include/ui/CameraHardwareInterface.h | 2 | ||||
-rw-r--r-- | include/ui/ICameraClient.h | 3 | ||||
-rw-r--r-- | libs/ui/Camera.cpp | 13 | ||||
-rw-r--r-- | libs/ui/ICameraClient.cpp | 23 | ||||
-rw-r--r-- | services/java/com/android/server/NotificationManagerService.java | 16 | ||||
-rw-r--r-- | services/java/com/android/server/SystemServer.java | 10 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 22 |
19 files changed, 537 insertions, 42 deletions
diff --git a/api/current.xml b/api/current.xml index d97a0f4..a396c4d 100644 --- a/api/current.xml +++ b/api/current.xml @@ -496,6 +496,17 @@ visibility="public" > </field> +<field name="GLOBAL_SEARCH" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.permission.GLOBAL_SEARCH"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="HARDWARE_TEST" type="java.lang.String" transient="false" @@ -25945,6 +25956,17 @@ visibility="public" > </method> +<method name="getPathPermissions" + return="android.content.pm.PathPermission[]" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getReadPermission" return="java.lang.String" abstract="false" @@ -26113,6 +26135,19 @@ <parameter name="sortOrder" type="java.lang.String"> </parameter> </method> +<method name="setPathPermissions" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="true" + deprecated="not deprecated" + visibility="protected" +> +<parameter name="permissions" type="android.content.pm.PathPermission[]"> +</parameter> +</method> <method name="setReadPermission" return="void" abstract="false" @@ -37714,6 +37749,73 @@ > </field> </class> +<class name="PathPermission" + extends="android.os.PatternMatcher" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<constructor name="PathPermission" + type="android.content.pm.PathPermission" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="pattern" type="java.lang.String"> +</parameter> +<parameter name="type" type="int"> +</parameter> +<parameter name="readPermission" type="java.lang.String"> +</parameter> +<parameter name="writePermission" type="java.lang.String"> +</parameter> +</constructor> +<constructor name="PathPermission" + type="android.content.pm.PathPermission" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="src" type="android.os.Parcel"> +</parameter> +</constructor> +<method name="getReadPermission" + return="java.lang.String" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="getWritePermission" + return="java.lang.String" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<field name="CREATOR" + type="android.os.Parcelable.Creator" + transient="false" + volatile="false" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +</class> <class name="PermissionGroupInfo" extends="android.content.pm.PackageItemInfo" abstract="false" @@ -38043,6 +38145,17 @@ visibility="public" > </field> +<field name="pathPermissions" + type="android.content.pm.PathPermission[]" + transient="false" + volatile="false" + value="null" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="readPermission" type="java.lang.String" transient="false" diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp index 022fe5a..e4b6791 100644 --- a/camera/libcameraservice/CameraService.cpp +++ b/camera/libcameraservice/CameraService.cpp @@ -504,8 +504,7 @@ status_t CameraService::Client::startRecordingMode() } // start recording mode - ret = mHardware->startRecording(recordingCallback, - mCameraService.get()); + ret = mHardware->startRecording(recordingCallback, mCameraService.get()); if (ret != NO_ERROR) { LOGE("mHardware->startRecording() failed with status %d", ret); } @@ -798,7 +797,7 @@ void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user) } // recording callback -void CameraService::Client::recordingCallback(const sp<IMemory>& mem, void* user) +void CameraService::Client::recordingCallback(nsecs_t timestamp, const sp<IMemory>& mem, void* user) { LOGV("recordingCallback"); sp<Client> client = getClientFromCookie(user); @@ -806,7 +805,7 @@ void CameraService::Client::recordingCallback(const sp<IMemory>& mem, void* user return; } // The strong pointer guarantees the client will exist, but no lock is held. - client->postRecordingFrame(mem); + client->postRecordingFrame(timestamp, mem); } // take a picture - image is returned in callback @@ -1072,14 +1071,14 @@ void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, si mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame); } -void CameraService::Client::postRecordingFrame(const sp<IMemory>& frame) +void CameraService::Client::postRecordingFrame(nsecs_t timestamp, const sp<IMemory>& frame) { LOGV("postRecordingFrame"); if (frame == 0) { LOGW("frame is a null pointer"); return; } - mCameraClient->dataCallback(CAMERA_MSG_VIDEO_FRAME, frame); + mCameraClient->dataCallbackTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, frame); } void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem) diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h index 0f07673..ea93789 100644 --- a/camera/libcameraservice/CameraService.h +++ b/camera/libcameraservice/CameraService.h @@ -132,7 +132,7 @@ private: status_t checkPid(); - static void recordingCallback(const sp<IMemory>& mem, void* user); + static void recordingCallback(nsecs_t timestamp, const sp<IMemory>& mem, void* user); static void previewCallback(const sp<IMemory>& mem, void* user); static void shutterCallback(void *user); static void yuvPictureCallback(const sp<IMemory>& mem, void* user); @@ -144,7 +144,7 @@ private: void postRaw(const sp<IMemory>& mem); void postJpeg(const sp<IMemory>& mem); void postPreviewFrame(const sp<IMemory>& mem); - void postRecordingFrame(const sp<IMemory>& frame); + void postRecordingFrame(nsecs_t timestamp, const sp<IMemory>& frame); void copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size); void postError(status_t error); void postAutoFocus(bool focused); diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 5cc5730..6b50405 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -17,6 +17,7 @@ package android.content; import android.content.pm.PackageManager; +import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; import android.content.res.AssetFileDescriptor; import android.content.res.Configuration; @@ -29,6 +30,7 @@ import android.database.SQLException; import android.net.Uri; import android.os.Binder; import android.os.ParcelFileDescriptor; +import android.os.Process; import java.io.File; import java.io.FileNotFoundException; @@ -65,8 +67,10 @@ import java.io.FileNotFoundException; */ public abstract class ContentProvider implements ComponentCallbacks { private Context mContext = null; + private int mMyUid; private String mReadPermission; private String mWritePermission; + private PathPermission[] mPathPermissions; private Transport mTransport = new Transport(); @@ -108,24 +112,20 @@ public abstract class ContentProvider implements ComponentCallbacks { public IBulkCursor bulkQuery(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder, IContentObserver observer, CursorWindow window) { - checkReadPermission(uri); + enforceReadPermission(uri); Cursor cursor = ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder); if (cursor == null) { return null; } - String wperm = getWritePermission(); return new CursorToBulkCursorAdaptor(cursor, observer, ContentProvider.this.getClass().getName(), - wperm == null || - getContext().checkCallingOrSelfPermission(getWritePermission()) - == PackageManager.PERMISSION_GRANTED, - window); + hasWritePermission(uri), window); } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - checkReadPermission(uri); + enforceReadPermission(uri); return ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder); } @@ -136,55 +136,84 @@ public abstract class ContentProvider implements ComponentCallbacks { public Uri insert(Uri uri, ContentValues initialValues) { - checkWritePermission(uri); + enforceWritePermission(uri); return ContentProvider.this.insert(uri, initialValues); } public int bulkInsert(Uri uri, ContentValues[] initialValues) { - checkWritePermission(uri); + enforceWritePermission(uri); return ContentProvider.this.bulkInsert(uri, initialValues); } public int delete(Uri uri, String selection, String[] selectionArgs) { - checkWritePermission(uri); + enforceWritePermission(uri); return ContentProvider.this.delete(uri, selection, selectionArgs); } public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - checkWritePermission(uri); + enforceWritePermission(uri); return ContentProvider.this.update(uri, values, selection, selectionArgs); } public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { - if (mode != null && mode.startsWith("rw")) checkWritePermission(uri); - else checkReadPermission(uri); + if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri); + else enforceReadPermission(uri); return ContentProvider.this.openFile(uri, mode); } public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException { - if (mode != null && mode.startsWith("rw")) checkWritePermission(uri); - else checkReadPermission(uri); + if (mode != null && mode.startsWith("rw")) enforceWritePermission(uri); + else enforceReadPermission(uri); return ContentProvider.this.openAssetFile(uri, mode); } public ISyncAdapter getSyncAdapter() { - checkWritePermission(null); + enforceWritePermission(null); SyncAdapter sa = ContentProvider.this.getSyncAdapter(); return sa != null ? sa.getISyncAdapter() : null; } - private void checkReadPermission(Uri uri) { + private void enforceReadPermission(Uri uri) { + final int uid = Binder.getCallingUid(); + if (uid == mMyUid) { + return; + } + + final Context context = getContext(); final String rperm = getReadPermission(); final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - if (getContext().checkUriPermission(uri, rperm, null, pid, uid, + if (rperm == null + || context.checkPermission(rperm, pid, uid) + == PackageManager.PERMISSION_GRANTED) { + return; + } + + PathPermission[] pps = getPathPermissions(); + if (pps != null) { + final String path = uri.getPath(); + int i = pps.length; + while (i > 0) { + i--; + final PathPermission pp = pps[i]; + final String pprperm = pp.getReadPermission(); + if (pprperm != null && pp.match(path)) { + if (context.checkPermission(pprperm, pid, uid) + == PackageManager.PERMISSION_GRANTED) { + return; + } + } + } + } + + if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION) == PackageManager.PERMISSION_GRANTED) { return; } + String msg = "Permission Denial: reading " + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + Binder.getCallingPid() @@ -193,20 +222,57 @@ public abstract class ContentProvider implements ComponentCallbacks { throw new SecurityException(msg); } - private void checkWritePermission(Uri uri) { + private boolean hasWritePermission(Uri uri) { + final int uid = Binder.getCallingUid(); + if (uid == mMyUid) { + return true; + } + + final Context context = getContext(); final String wperm = getWritePermission(); final int pid = Binder.getCallingPid(); - final int uid = Binder.getCallingUid(); - if (getContext().checkUriPermission(uri, null, wperm, pid, uid, + if (wperm == null + || context.checkPermission(wperm, pid, uid) + == PackageManager.PERMISSION_GRANTED) { + return true; + } + + PathPermission[] pps = getPathPermissions(); + if (pps != null) { + final String path = uri.getPath(); + int i = pps.length; + while (i > 0) { + i--; + final PathPermission pp = pps[i]; + final String ppwperm = pp.getWritePermission(); + if (ppwperm != null && pp.match(path)) { + if (context.checkPermission(ppwperm, pid, uid) + == PackageManager.PERMISSION_GRANTED) { + return true; + } + } + } + } + + if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == PackageManager.PERMISSION_GRANTED) { + return true; + } + + return false; + } + + private void enforceWritePermission(Uri uri) { + if (hasWritePermission(uri)) { return; } + String msg = "Permission Denial: writing " + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() - + " requires " + wperm; + + " requires " + getWritePermission(); throw new SecurityException(msg); } } @@ -266,6 +332,28 @@ public abstract class ContentProvider implements ComponentCallbacks { } /** + * Change the path-based permission required to read and/or write data in + * the content provider. This is normally set for you from its manifest + * information when the provider is first created. + * + * @param permissions Array of path permission descriptions. + */ + protected final void setPathPermissions(PathPermission[] permissions) { + mPathPermissions = permissions; + } + + /** + * Return the path-based permissions required for read and/or write access to + * this content provider. This method can be called from multiple + * threads, as described in + * <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals: + * Processes and Threads</a>. + */ + public final PathPermission[] getPathPermissions() { + return mPathPermissions; + } + + /** * Called when the provider is being started. * * @return true if the provider was successfully loaded, false otherwise @@ -600,9 +688,11 @@ public abstract class ContentProvider implements ComponentCallbacks { */ if (mContext == null) { mContext = context; + mMyUid = Process.myUid(); if (info != null) { setReadPermission(info.readPermission); setWritePermission(info.writePermission); + setPathPermissions(info.pathPermissions); } ContentProvider.this.onCreate(); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index b293636..0e2deed 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1918,6 +1918,7 @@ public class PackageParser { outInfo.metaData, outError)) == null) { return false; } + } else if (parser.getName().equals("grant-uri-permission")) { TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.AndroidManifestGrantUriPermission); @@ -1941,7 +1942,7 @@ public class PackageParser { if (str != null) { pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB); } - + sa.recycle(); if (pa != null) { @@ -1956,6 +1957,101 @@ public class PackageParser { outInfo.info.uriPermissionPatterns = newp; } outInfo.info.grantUriPermissions = true; + } else { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>"); + XmlUtils.skipCurrentTag(parser); + continue; + } + outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>"; + return false; + } + XmlUtils.skipCurrentTag(parser); + + } else if (parser.getName().equals("path-permission")) { + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestPathPermission); + + PathPermission pa = null; + + String permission = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_permission); + String readPermission = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_readPermission); + if (readPermission == null) { + readPermission = permission; + } + String writePermission = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_writePermission); + if (writePermission == null) { + writePermission = permission; + } + + boolean havePerm = false; + if (readPermission != null) { + readPermission = readPermission.intern(); + havePerm = true; + } + if (writePermission != null) { + writePermission = readPermission.intern(); + havePerm = true; + } + + if (!havePerm) { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "No readPermission or writePermssion for <path-permission>"); + XmlUtils.skipCurrentTag(parser); + continue; + } + outError[0] = "No readPermission or writePermssion for <path-permission>"; + return false; + } + + String path = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_path); + if (path != null) { + pa = new PathPermission(path, + PatternMatcher.PATTERN_LITERAL, readPermission, writePermission); + } + + path = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_pathPrefix); + if (path != null) { + pa = new PathPermission(path, + PatternMatcher.PATTERN_PREFIX, readPermission, writePermission); + } + + path = sa.getNonResourceString( + com.android.internal.R.styleable.AndroidManifestPathPermission_pathPattern); + if (path != null) { + pa = new PathPermission(path, + PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission); + } + + sa.recycle(); + + if (pa != null) { + if (outInfo.info.pathPermissions == null) { + outInfo.info.pathPermissions = new PathPermission[1]; + outInfo.info.pathPermissions[0] = pa; + } else { + final int N = outInfo.info.pathPermissions.length; + PathPermission[] newp = new PathPermission[N+1]; + System.arraycopy(outInfo.info.pathPermissions, 0, newp, 0, N); + newp[N] = pa; + outInfo.info.pathPermissions = newp; + } + } else { + if (!RIGID_PARSER) { + Log.w(TAG, "Problem in package " + mArchiveSourcePath + ":"); + Log.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>"); + XmlUtils.skipCurrentTag(parser); + continue; + } + outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>"; + return false; } XmlUtils.skipCurrentTag(parser); diff --git a/core/java/android/content/pm/PathPermission.java b/core/java/android/content/pm/PathPermission.java new file mode 100644 index 0000000..7e49d7d --- /dev/null +++ b/core/java/android/content/pm/PathPermission.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.pm; + +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PatternMatcher; + +/** + * Description of permissions needed to access a particular path + * in a {@link ProviderInfo}. + */ +public class PathPermission extends PatternMatcher { + private final String mReadPermission; + private final String mWritePermission; + + public PathPermission(String pattern, int type, String readPermission, + String writePermission) { + super(pattern, type); + mReadPermission = readPermission; + mWritePermission = writePermission; + } + + public String getReadPermission() { + return mReadPermission; + } + + public String getWritePermission() { + return mWritePermission; + } + + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeString(mReadPermission); + dest.writeString(mWritePermission); + } + + public PathPermission(Parcel src) { + super(src); + mReadPermission = src.readString(); + mWritePermission = src.readString(); + } + + public static final Parcelable.Creator<PathPermission> CREATOR + = new Parcelable.Creator<PathPermission>() { + public PathPermission createFromParcel(Parcel source) { + return new PathPermission(source); + } + + public PathPermission[] newArray(int size) { + return new PathPermission[size]; + } + }; +}
\ No newline at end of file diff --git a/core/java/android/content/pm/ProviderInfo.java b/core/java/android/content/pm/ProviderInfo.java index b67ddf6..d01460e 100644 --- a/core/java/android/content/pm/ProviderInfo.java +++ b/core/java/android/content/pm/ProviderInfo.java @@ -28,6 +28,7 @@ import android.os.PatternMatcher; */ public final class ProviderInfo extends ComponentInfo implements Parcelable { + /** The name provider is published under content:// */ public String authority = null; @@ -56,6 +57,14 @@ public final class ProviderInfo extends ComponentInfo */ public PatternMatcher[] uriPermissionPatterns = null; + /** + * If non-null, these are path-specific permissions that are allowed for + * accessing the provider. Any permissions listed here will allow a + * holding client to access the provider, and the provider will check + * the URI it provides when making calls against the patterns here. + */ + public PathPermission[] pathPermissions = null; + /** If true, this content provider allows multiple instances of itself * to run in different process. If false, a single instances is always * run in {@link #processName}. */ @@ -78,6 +87,7 @@ public final class ProviderInfo extends ComponentInfo writePermission = orig.writePermission; grantUriPermissions = orig.grantUriPermissions; uriPermissionPatterns = orig.uriPermissionPatterns; + pathPermissions = orig.pathPermissions; multiprocess = orig.multiprocess; initOrder = orig.initOrder; isSyncable = orig.isSyncable; @@ -94,6 +104,7 @@ public final class ProviderInfo extends ComponentInfo out.writeString(writePermission); out.writeInt(grantUriPermissions ? 1 : 0); out.writeTypedArray(uriPermissionPatterns, parcelableFlags); + out.writeTypedArray(pathPermissions, parcelableFlags); out.writeInt(multiprocess ? 1 : 0); out.writeInt(initOrder); out.writeInt(isSyncable ? 1 : 0); @@ -122,6 +133,7 @@ public final class ProviderInfo extends ComponentInfo writePermission = in.readString(); grantUriPermissions = in.readInt() != 0; uriPermissionPatterns = in.createTypedArray(PatternMatcher.CREATOR); + pathPermissions = in.createTypedArray(PathPermission.CREATOR); multiprocess = in.readInt() != 0; initOrder = in.readInt(); isSyncable = in.readInt() != 0; diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index f90cbff..ed1e4ff 100644 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -606,6 +606,7 @@ public class TextToSpeech { result = mITts.setLanguage(mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1], mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1], mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] ); + } catch (RemoteException e) { // TTS died; restart it. mStarted = false; initTts(); diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index 77a8a72..57b5aa6 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -55,6 +55,7 @@ public: ~JNICameraContext() { release(); } virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2); virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr); + virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; } void release(); @@ -188,6 +189,12 @@ void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr) } } +void JNICameraContext::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) +{ + // TODO: plumb up to Java. For now, just drop the timestamp + postData(msgType, dataPtr); +} + // connect to camera service static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this) { diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 599360f..23967f4 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -995,6 +995,29 @@ android:description="@string/permdesc_changeBackgroundDataSetting" android:label="@string/permlab_changeBackgroundDataSetting" /> + <!-- This permission can be used on content providers to allow the global + search system to access their data. Typically it used when the + provider has some permissions protecting it (which global search + would not be expected to hold), and added as a read-only permission + to the path in the provider where global search queries are + performed. This permission can not be held by regular applications; + it is used by applications to protect themselves from everyone else + besides global search. --> + <permission android:name="android.permission.GLOBAL_SEARCH" + android:permissionGroup="android.permission-group.SYSTEM_TOOLS" + android:protectionLevel="signatureOrSystem" /> + + <!-- Internal permission protecting access to the global search + system: ensures that only the system can access the provider + to perform queries (since this otherwise provides unrestricted + access to a variety of content providers), and to write the + search statistics (to keep applications from gaming the source + ranking). + @hide --> + <permission android:name="android.permission.GLOBAL_SEARCH_CONTROL" + android:permissionGroup="android.permission-group.SYSTEM_TOOLS" + android:protectionLevel="signature" /> + <application android:process="system" android:persistent="true" android:hasCode="false" diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 7571e24..12a76ba 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -953,6 +953,20 @@ <attr name="pathPattern" format="string" /> </declare-styleable> + <!-- Attributes that can be supplied in an AndroidManifest.xml + <code>path-permission</code> tag, a child of the + {@link #AndroidManifestProvider provider} tag, describing a permission + that allows access to a specific path in the provider. This tag can be + specified multiple time to supply multiple paths. --> + <declare-styleable name="AndroidManifestPathPermission" parent="AndroidManifestProvider"> + <attr name="path" /> + <attr name="pathPrefix" /> + <attr name="pathPattern" /> + <attr name="permission" /> + <attr name="readPermission" /> + <attr name="writePermission" /> + </declare-styleable> + <!-- The <code>service</code> tag declares a {@link android.app.Service} class that is available as part of the package's application components, implementing diff --git a/include/ui/Camera.h b/include/ui/Camera.h index e3544ab..afb07b5 100644 --- a/include/ui/Camera.h +++ b/include/ui/Camera.h @@ -18,6 +18,7 @@ #ifndef ANDROID_HARDWARE_CAMERA_H #define ANDROID_HARDWARE_CAMERA_H +#include <utils/Timers.h> #include <ui/ICameraClient.h> namespace android { @@ -94,6 +95,7 @@ class CameraListener: virtual public RefBase public: virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr) = 0; + virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) = 0; }; class Camera : public BnCameraClient, public IBinder::DeathRecipient @@ -155,6 +157,7 @@ public: // ICameraClient interface virtual void notifyCallback(int32_t msgType, int32_t ext, int32_t ext2); virtual void dataCallback(int32_t msgType, const sp<IMemory>& dataPtr); + virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr); sp<ICamera> remote(); diff --git a/include/ui/CameraHardwareInterface.h b/include/ui/CameraHardwareInterface.h index 73036f0..822b4a8 100644 --- a/include/ui/CameraHardwareInterface.h +++ b/include/ui/CameraHardwareInterface.h @@ -28,7 +28,7 @@ namespace android { typedef void (*preview_callback)(const sp<IMemory>& mem, void* user); /** Callback for startRecord() */ -typedef void (*recording_callback)(const sp<IMemory>& mem, void* user); +typedef void (*recording_callback)(nsecs_t timestamp, const sp<IMemory>& mem, void* user); /** Callback for takePicture() */ typedef void (*shutter_callback)(void* user); diff --git a/include/ui/ICameraClient.h b/include/ui/ICameraClient.h index c4bdd07..1001c71 100644 --- a/include/ui/ICameraClient.h +++ b/include/ui/ICameraClient.h @@ -21,6 +21,7 @@ #include <utils/IInterface.h> #include <utils/Parcel.h> #include <utils/IMemory.h> +#include <utils/Timers.h> namespace android { @@ -31,7 +32,7 @@ public: virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0; virtual void dataCallback(int32_t msgType, const sp<IMemory>& data) = 0; - + virtual void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0; }; // ---------------------------------------------------------------------------- diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp index 975594f..5015379 100644 --- a/libs/ui/Camera.cpp +++ b/libs/ui/Camera.cpp @@ -310,6 +310,19 @@ void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr) } } +// callback from camera service when timestamped frame is ready +void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) +{ + sp<CameraListener> listener; + { + Mutex::Autolock _l(mLock); + listener = mListener; + } + if (listener != NULL) { + listener->postDataTimestamp(timestamp, msgType, dataPtr); + } +} + void Camera::binderDied(const wp<IBinder>& who) { LOGW("ICamera died"); notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_SERVER_DIED, 0); diff --git a/libs/ui/ICameraClient.cpp b/libs/ui/ICameraClient.cpp index c6cf75c..59a6cf2 100644 --- a/libs/ui/ICameraClient.cpp +++ b/libs/ui/ICameraClient.cpp @@ -27,6 +27,7 @@ namespace android { enum { NOTIFY_CALLBACK = IBinder::FIRST_CALL_TRANSACTION, DATA_CALLBACK, + DATA_CALLBACK_TIMESTAMP, }; class BpCameraClient: public BpInterface<ICameraClient> @@ -60,6 +61,17 @@ public: remote()->transact(DATA_CALLBACK, data, &reply, IBinder::FLAG_ONEWAY); } + // generic data callback from camera service to app with image data + void dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& imageData) + { + LOGV("dataCallback"); + Parcel data, reply; + data.writeInterfaceToken(ICameraClient::getInterfaceDescriptor()); + data.writeInt64(timestamp); + data.writeInt32(msgType); + data.writeStrongBinder(imageData->asBinder()); + remote()->transact(DATA_CALLBACK_TIMESTAMP, data, &reply, IBinder::FLAG_ONEWAY); + } }; IMPLEMENT_META_INTERFACE(CameraClient, "android.hardware.ICameraClient"); @@ -86,13 +98,22 @@ status_t BnCameraClient::onTransact( return NO_ERROR; } break; case DATA_CALLBACK: { - LOGV("RAW_CALLBACK"); + LOGV("DATA_CALLBACK"); CHECK_INTERFACE(ICameraClient, data, reply); int32_t msgType = data.readInt32(); sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder()); dataCallback(msgType, imageData); return NO_ERROR; } break; + case DATA_CALLBACK_TIMESTAMP: { + LOGV("DATA_CALLBACK_TIMESTAMP"); + CHECK_INTERFACE(ICameraClient, data, reply); + nsecs_t timestamp = data.readInt64(); + int32_t msgType = data.readInt32(); + sp<IMemory> imageData = interface_cast<IMemory>(data.readStrongBinder()); + dataCallbackTimestamp(timestamp, msgType, imageData); + return NO_ERROR; + } break; default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 854138c..190d3e6 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -88,7 +88,8 @@ class NotificationManagerService extends INotificationManager.Stub private NotificationRecord mSoundNotification; private AsyncPlayer mSound; - private int mDisabledNotifications; + private boolean mSystemReady; + private int mDisabledNotifications = StatusBarManager.DISABLE_NOTIFICATION_ALERTS; private NotificationRecord mVibrateNotification; private Vibrator mVibrator = new Vibrator(); @@ -377,6 +378,11 @@ class NotificationManagerService extends INotificationManager.Stub mSettingsObserver.observe(); } + void systemReady() { + // no beeping until we're basically done booting + mSystemReady = true; + } + // Toasts // ============================================================================ public void enqueueToast(String pkg, ITransientNotification callback, int duration) @@ -637,7 +643,7 @@ class NotificationManagerService extends INotificationManager.Stub } } - sendAccessibilityEventTypeNotificationChangedDoCheck(notification, pkg); + sendAccessibilityEvent(notification, pkg); } else { if (old != null && old.statusBarKey != null) { @@ -654,7 +660,8 @@ class NotificationManagerService extends INotificationManager.Stub // If we're not supposed to beep, vibrate, etc. then don't. if (((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0) && (!(old != null - && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))) { + && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 )) + && mSystemReady) { // sound final boolean useDefaultSound = (notification.defaults & Notification.DEFAULT_SOUND) != 0; @@ -721,8 +728,7 @@ class NotificationManagerService extends INotificationManager.Stub idOut[0] = id; } - private void sendAccessibilityEventTypeNotificationChangedDoCheck(Notification notification, - CharSequence packageName) { + private void sendAccessibilityEvent(Notification notification, CharSequence packageName) { AccessibilityManager manager = AccessibilityManager.getInstance(mContext); if (!manager.isEnabled()) { return; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 3e4d5f9..b038a64 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -190,6 +190,7 @@ class ServerThread extends Thread { StatusBarService statusBar = null; InputMethodManagerService imm = null; AppWidgetService appWidget = null; + NotificationManagerService notification = null; if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { @@ -240,8 +241,8 @@ class ServerThread extends Thread { try { Log.i(TAG, "Starting Notification Manager."); - ServiceManager.addService(Context.NOTIFICATION_SERVICE, - new NotificationManagerService(context, statusBar, hardware)); + notification = new NotificationManagerService(context, statusBar, hardware); + ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification); } catch (Throwable e) { Log.e(TAG, "Failure starting Notification Manager", e); } @@ -348,6 +349,11 @@ class ServerThread extends Thread { // It is now time to start up the app processes... boolean safeMode = wm.detectSafeMode(); + + if (notification != null) { + notification.systemReady(); + } + if (statusBar != null) { statusBar.systemReady(); } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 2fe4dd4..aad542a 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -56,6 +56,7 @@ import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageManager; +import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; @@ -7072,6 +7073,27 @@ public final class ActivityManagerService extends ActivityManagerNative implemen == PackageManager.PERMISSION_GRANTED) { return null; } + + PathPermission[] pps = cpi.pathPermissions; + if (pps != null) { + int i = pps.length; + while (i > 0) { + i--; + PathPermission pp = pps[i]; + if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid, + cpi.exported ? -1 : cpi.applicationInfo.uid) + == PackageManager.PERMISSION_GRANTED + && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) { + return null; + } + if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid, + cpi.exported ? -1 : cpi.applicationInfo.uid) + == PackageManager.PERMISSION_GRANTED) { + return null; + } + } + } + String msg = "Permission Denial: opening provider " + cpi.name + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid + ", uid=" + callingUid + ") requires " |