Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45182959 authored by Dan Pasanen's avatar Dan Pasanen
Browse files

Merge tag 'android-7.1.1_r21' into cm-14.1

Android 7.1.1 release 21

Change-Id: I7c02d26bcafa2ef24686c4f7637ce13d74c04d3a
parents 63ec5410 c639cb67
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -60,6 +60,11 @@ public abstract class ActivityManagerInternal {
     */
    public static final int APP_TRANSITION_TIMEOUT = 3;

    /**
     * Verify that calling app has access to the given provider.
     */
    public abstract String checkContentProviderAccess(String authority, int userId);

    // Called by the power manager.
    public abstract void onWakefulnessChanged(int wakefulness);

+60 −12
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@ import android.system.StructStat;
import android.util.Log;

import com.google.android.collect.Maps;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.XmlUtils;

import dalvik.system.BlockGuard;
@@ -72,6 +74,14 @@ final class SharedPreferencesImpl implements SharedPreferences {
    private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
            new WeakHashMap<OnSharedPreferenceChangeListener, Object>();

    /** Current memory state (always increasing) */
    @GuardedBy("this")
    private long mCurrentMemoryStateGeneration;

    /** Latest memory state that was committed to disk */
    @GuardedBy("mWritingToDiskLock")
    private long mDiskStateGeneration;

    SharedPreferencesImpl(File file, int mode) {
        mFile = file;
        mBackupFile = makeBackupFile(file);
@@ -289,7 +299,7 @@ final class SharedPreferencesImpl implements SharedPreferences {

    // Return value from EditorImpl#commitToMemory()
    private static class MemoryCommitResult {
        public boolean changesMade;  // any keys different?
        public long memoryStateGeneration;
        public List<String> keysModified;  // may be null
        public Set<OnSharedPreferenceChangeListener> listeners;  // may be null
        public Map<?, ?> mapToWriteToDisk;
@@ -412,9 +422,11 @@ final class SharedPreferencesImpl implements SharedPreferences {
                }

                synchronized (this) {
                    boolean changesMade = false;

                    if (mClear) {
                        if (!mMap.isEmpty()) {
                            mcr.changesMade = true;
                            changesMade = true;
                            mMap.clear();
                        }
                        mClear = false;
@@ -441,13 +453,19 @@ final class SharedPreferencesImpl implements SharedPreferences {
                            mMap.put(k, v);
                        }

                        mcr.changesMade = true;
                        changesMade = true;
                        if (hasListeners) {
                            mcr.keysModified.add(k);
                        }
                    }

                    mModified.clear();

                    if (changesMade) {
                        mCurrentMemoryStateGeneration++;
                    }

                    mcr.memoryStateGeneration = mCurrentMemoryStateGeneration;
                }
            }
            return mcr;
@@ -509,10 +527,12 @@ final class SharedPreferencesImpl implements SharedPreferences {
     */
    private void enqueueDiskWrite(final MemoryCommitResult mcr,
                                  final Runnable postWriteRunnable) {
        final boolean isFromSyncCommit = (postWriteRunnable == null);

        final Runnable writeToDiskRunnable = new Runnable() {
                public void run() {
                    synchronized (mWritingToDiskLock) {
                        writeToFile(mcr);
                        writeToFile(mcr, isFromSyncCommit);
                    }
                    synchronized (SharedPreferencesImpl.this) {
                        mDiskWritesInFlight--;
@@ -523,8 +543,6 @@ final class SharedPreferencesImpl implements SharedPreferences {
                }
            };

        final boolean isFromSyncCommit = (postWriteRunnable == null);

        // Typical #commit() path with fewer allocations, doing a write on
        // the current thread.
        if (isFromSyncCommit) {
@@ -538,6 +556,10 @@ final class SharedPreferencesImpl implements SharedPreferences {
            }
        }

        if (DEBUG) {
            Log.d(TAG, "added " + mcr.memoryStateGeneration + " -> " + mFile.getName());
        }

        QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
    }

@@ -565,17 +587,34 @@ final class SharedPreferencesImpl implements SharedPreferences {
    }

    // Note: must hold mWritingToDiskLock
    private void writeToFile(MemoryCommitResult mcr) {
    private void writeToFile(MemoryCommitResult mcr, boolean isFromSyncCommit) {
        // Rename the current file so it may be used as a backup during the next read
        if (mFile.exists()) {
            if (!mcr.changesMade) {
                // If the file already exists, but no changes were
                // made to the underlying map, it's wasteful to
                // re-write the file.  Return as if we wrote it
                // out.
            boolean needsWrite = false;

            // Only need to write if the disk state is older than this commit
            if (mDiskStateGeneration < mcr.memoryStateGeneration) {
                if (isFromSyncCommit) {
                    needsWrite = true;
                } else {
                    synchronized (this) {
                        // No need to persist intermediate states. Just wait for the latest state to
                        // be persisted.
                        if (mCurrentMemoryStateGeneration == mcr.memoryStateGeneration) {
                            needsWrite = true;
                        }
                    }
                }
            }

            if (!needsWrite) {
                if (DEBUG) {
                    Log.d(TAG, "skipped " + mcr.memoryStateGeneration + " -> " + mFile.getName());
                }
                mcr.setDiskWriteResult(true);
                return;
            }

            if (!mBackupFile.exists()) {
                if (!mFile.renameTo(mBackupFile)) {
                    Log.e(TAG, "Couldn't rename file " + mFile
@@ -599,6 +638,11 @@ final class SharedPreferencesImpl implements SharedPreferences {
            }
            XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
            FileUtils.sync(str);

            if (DEBUG) {
                Log.d(TAG, "wrote " + mcr.memoryStateGeneration + " -> " + mFile.getName());
            }

            str.close();
            ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
            try {
@@ -612,7 +656,11 @@ final class SharedPreferencesImpl implements SharedPreferences {
            }
            // Writing was successful, delete the backup file if there is one.
            mBackupFile.delete();

            mDiskStateGeneration = mcr.memoryStateGeneration;

            mcr.setDiskWriteResult(true);

            return;
        } catch (XmlPullParserException e) {
            Log.w(TAG, "writeToFile: Got exception:", e);
+2 −0
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ public final class Downloads {
    public static final class Impl implements BaseColumns {
        private Impl() {}

        public static final String AUTHORITY = "downloads";

        /**
         * The permission to access the download manager
         */
+21 −37
Original line number Diff line number Diff line
@@ -35,13 +35,13 @@ import java.util.UUID;
 * each other.
 * <p>
 * The data structure is designed to have one owner process that can
 * read/write. There may be multiple client processes that can only read or
 * read/write depending how the data structure was configured when
 * instantiated. The owner process is the process that created the array.
 * The shared memory is pinned (not reclaimed by the system) until the
 * owning process dies or the data structure is closed. This class
 * is <strong>not</strong> thread safe. You should not interact with
 * an instance of this class once it is closed.
 * read/write. There may be multiple client processes that can only read.
 * The owner process is the process that created the array. The shared
 * memory is pinned (not reclaimed by the system) until the owning process
 * dies or the data structure is closed. This class is <strong>not</strong>
 * thread safe. You should not interact with an instance of this class
 * once it is closed. If you pass back to the owner process an instance
 * it will be read only even in the owning process.
 * </p>
 *
 * @hide
@@ -51,8 +51,7 @@ public final class MemoryIntArray implements Parcelable, Closeable {

    private static final int MAX_SIZE = 1024;

    private final int mOwnerPid;
    private final boolean mClientWritable;
    private final boolean mIsOwner;
    private final long mMemoryAddr;
    private int mFd;

@@ -64,31 +63,24 @@ public final class MemoryIntArray implements Parcelable, Closeable {
     * @param clientWritable Whether other processes can write to the array.
     * @throws IOException If an error occurs while accessing the shared memory.
     */
    public MemoryIntArray(int size, boolean clientWritable) throws IOException {
    public MemoryIntArray(int size) throws IOException {
        if (size > MAX_SIZE) {
            throw new IllegalArgumentException("Max size is " + MAX_SIZE);
        }
        mOwnerPid = Process.myPid();
        mClientWritable = clientWritable;
        mIsOwner = true;
        final String name = UUID.randomUUID().toString();
        mFd = nativeCreate(name, size);
        mMemoryAddr = nativeOpen(mFd, true, clientWritable);
        mMemoryAddr = nativeOpen(mFd, mIsOwner);
    }

    private MemoryIntArray(Parcel parcel) throws IOException {
        mOwnerPid = parcel.readInt();
        mClientWritable = (parcel.readInt() == 1);
        mIsOwner = false;
        ParcelFileDescriptor pfd = parcel.readParcelable(null);
        if (pfd == null) {
            throw new IOException("No backing file descriptor");
        }
        mFd = pfd.detachFd();
        final long memoryAddress = parcel.readLong();
        if (isOwner()) {
            mMemoryAddr = memoryAddress;
        } else {
            mMemoryAddr = nativeOpen(mFd, false, mClientWritable);
        }
        mMemoryAddr = nativeOpen(mFd, mIsOwner);
    }

    /**
@@ -96,7 +88,7 @@ public final class MemoryIntArray implements Parcelable, Closeable {
     */
    public boolean isWritable() {
        enforceNotClosed();
        return isOwner() || mClientWritable;
        return mIsOwner;
    }

    /**
@@ -109,7 +101,7 @@ public final class MemoryIntArray implements Parcelable, Closeable {
    public int get(int index) throws IOException {
        enforceNotClosed();
        enforceValidIndex(index);
        return nativeGet(mFd, mMemoryAddr, index, isOwner());
        return nativeGet(mFd, mMemoryAddr, index);
    }

    /**
@@ -125,7 +117,7 @@ public final class MemoryIntArray implements Parcelable, Closeable {
        enforceNotClosed();
        enforceWritable();
        enforceValidIndex(index);
        nativeSet(mFd, mMemoryAddr, index, value, isOwner());
        nativeSet(mFd, mMemoryAddr, index, value);
    }

    /**
@@ -146,7 +138,7 @@ public final class MemoryIntArray implements Parcelable, Closeable {
    @Override
    public void close() throws IOException {
        if (!isClosed()) {
            nativeClose(mFd, mMemoryAddr, isOwner());
            nativeClose(mFd, mMemoryAddr, mIsOwner);
            mFd = -1;
        }
    }
@@ -173,10 +165,7 @@ public final class MemoryIntArray implements Parcelable, Closeable {
    public void writeToParcel(Parcel parcel, int flags) {
        ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(mFd);
        try {
            parcel.writeInt(mOwnerPid);
            parcel.writeInt(mClientWritable ? 1 : 0);
            parcel.writeParcelable(pfd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
            parcel.writeLong(mMemoryAddr);
        } finally {
            pfd.detachFd();
        }
@@ -202,10 +191,6 @@ public final class MemoryIntArray implements Parcelable, Closeable {
        return mFd;
    }

    private boolean isOwner() {
        return mOwnerPid == Process.myPid();
    }

    private void enforceNotClosed() {
        if (isClosed()) {
            throw new IllegalStateException("cannot interact with a closed instance");
@@ -227,10 +212,10 @@ public final class MemoryIntArray implements Parcelable, Closeable {
    }

    private native int nativeCreate(String name, int size);
    private native long nativeOpen(int fd, boolean owner, boolean writable);
    private native long nativeOpen(int fd, boolean owner);
    private native void nativeClose(int fd, long memoryAddr, boolean owner);
    private native int nativeGet(int fd, long memoryAddr, int index, boolean owner);
    private native void nativeSet(int fd, long memoryAddr, int index, int value, boolean owner);
    private native int nativeGet(int fd, long memoryAddr, int index);
    private native void nativeSet(int fd, long memoryAddr, int index, int value);
    private native int nativeSize(int fd);

    /**
@@ -247,8 +232,7 @@ public final class MemoryIntArray implements Parcelable, Closeable {
            try {
                return new MemoryIntArray(parcel);
            } catch (IOException ioe) {
                Log.e(TAG, "Error unparceling MemoryIntArray");
                return null;
                throw new IllegalArgumentException("Error unparceling MemoryIntArray");
            }
        }

+2 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.UserHandle;
import android.provider.Settings;

/**
@@ -72,7 +73,7 @@ public class EmergencyAffordanceManager {
        Intent intent = new Intent(Intent.ACTION_CALL_EMERGENCY);
        intent.setData(getPhoneUri(context));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
        context.startActivityAsUser(intent, UserHandle.CURRENT);
    }

    /**
Loading