Merge "Create Attribution Chains in HistoricalOps" into sc-dev am: 3e51f7cabd
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14963609 Change-Id: I9e6f201a7fe728ad4f1b914ac206467fac7f6769
This commit is contained in:
@@ -4803,6 +4803,16 @@ public class AppOpsManager {
|
||||
@SystemApi
|
||||
public static final int HISTORY_FLAG_DISCRETE = 1 << 1;
|
||||
|
||||
/**
|
||||
* Flag for querying app op history: assemble attribution chains, and attach the last visible
|
||||
* node in the chain to the start as a proxy info. This only applies to discrete accesses.
|
||||
*
|
||||
* TODO 191512294: Add to @SystemApi
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int HISTORY_FLAG_GET_ATTRIBUTION_CHAINS = 1 << 2;
|
||||
|
||||
/**
|
||||
* Flag for querying app op history: get all types of historical access information.
|
||||
*
|
||||
@@ -4819,7 +4829,8 @@ public class AppOpsManager {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(flag = true, prefix = { "HISTORY_FLAG_" }, value = {
|
||||
HISTORY_FLAG_AGGREGATE,
|
||||
HISTORY_FLAG_DISCRETE
|
||||
HISTORY_FLAG_DISCRETE,
|
||||
HISTORY_FLAG_GET_ATTRIBUTION_CHAINS
|
||||
})
|
||||
public @interface OpHistoryFlags {}
|
||||
|
||||
@@ -5037,7 +5048,8 @@ public class AppOpsManager {
|
||||
* @return This builder.
|
||||
*/
|
||||
public @NonNull Builder setHistoryFlags(@OpHistoryFlags int flags) {
|
||||
Preconditions.checkFlagsArgument(flags, HISTORY_FLAGS_ALL);
|
||||
Preconditions.checkFlagsArgument(flags,
|
||||
HISTORY_FLAGS_ALL | HISTORY_FLAG_GET_ATTRIBUTION_CHAINS);
|
||||
mHistoryFlags = flags;
|
||||
return this;
|
||||
}
|
||||
@@ -5290,8 +5302,17 @@ public class AppOpsManager {
|
||||
@Nullable String attributionTag, @UidState int uidState, @OpFlags int opFlag,
|
||||
long discreteAccessTime, long discreteAccessDuration) {
|
||||
getOrCreateHistoricalUidOps(uid).addDiscreteAccess(opCode, packageName, attributionTag,
|
||||
uidState, opFlag, discreteAccessTime, discreteAccessDuration);
|
||||
};
|
||||
uidState, opFlag, discreteAccessTime, discreteAccessDuration, null);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void addDiscreteAccess(int opCode, int uid, @NonNull String packageName,
|
||||
@Nullable String attributionTag, @UidState int uidState, @OpFlags int opFlag,
|
||||
long discreteAccessTime, long discreteAccessDuration,
|
||||
@Nullable OpEventProxyInfo proxy) {
|
||||
getOrCreateHistoricalUidOps(uid).addDiscreteAccess(opCode, packageName, attributionTag,
|
||||
uidState, opFlag, discreteAccessTime, discreteAccessDuration, proxy);
|
||||
}
|
||||
|
||||
|
||||
/** @hide */
|
||||
@@ -5623,9 +5644,10 @@ public class AppOpsManager {
|
||||
|
||||
private void addDiscreteAccess(int opCode, @NonNull String packageName,
|
||||
@Nullable String attributionTag, @UidState int uidState,
|
||||
@OpFlags int flag, long discreteAccessTime, long discreteAccessDuration) {
|
||||
@OpFlags int flag, long discreteAccessTime, long discreteAccessDuration,
|
||||
@Nullable OpEventProxyInfo proxy) {
|
||||
getOrCreateHistoricalPackageOps(packageName).addDiscreteAccess(opCode, attributionTag,
|
||||
uidState, flag, discreteAccessTime, discreteAccessDuration);
|
||||
uidState, flag, discreteAccessTime, discreteAccessDuration, proxy);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -5889,9 +5911,9 @@ public class AppOpsManager {
|
||||
|
||||
private void addDiscreteAccess(int opCode, @Nullable String attributionTag,
|
||||
@UidState int uidState, @OpFlags int flag, long discreteAccessTime,
|
||||
long discreteAccessDuration) {
|
||||
long discreteAccessDuration, @Nullable OpEventProxyInfo proxy) {
|
||||
getOrCreateAttributedHistoricalOps(attributionTag).addDiscreteAccess(opCode, uidState,
|
||||
flag, discreteAccessTime, discreteAccessDuration);
|
||||
flag, discreteAccessTime, discreteAccessDuration, proxy);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6212,9 +6234,10 @@ public class AppOpsManager {
|
||||
}
|
||||
|
||||
private void addDiscreteAccess(int opCode, @UidState int uidState, @OpFlags int flag,
|
||||
long discreteAccessTime, long discreteAccessDuration) {
|
||||
long discreteAccessTime, long discreteAccessDuration,
|
||||
@Nullable OpEventProxyInfo proxy) {
|
||||
getOrCreateHistoricalOp(opCode).addDiscreteAccess(uidState,flag, discreteAccessTime,
|
||||
discreteAccessDuration);
|
||||
discreteAccessDuration, proxy);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6583,11 +6606,12 @@ public class AppOpsManager {
|
||||
}
|
||||
|
||||
private void addDiscreteAccess(@UidState int uidState, @OpFlags int flag,
|
||||
long discreteAccessTime, long discreteAccessDuration) {
|
||||
long discreteAccessTime, long discreteAccessDuration,
|
||||
@Nullable OpEventProxyInfo proxy) {
|
||||
List<AttributedOpEntry> discreteAccesses = getOrCreateDiscreteAccesses();
|
||||
LongSparseArray<NoteOpEvent> accessEvents = new LongSparseArray<>();
|
||||
long key = makeKey(uidState, flag);
|
||||
NoteOpEvent note = new NoteOpEvent(discreteAccessTime, discreteAccessDuration, null);
|
||||
NoteOpEvent note = new NoteOpEvent(discreteAccessTime, discreteAccessDuration, proxy);
|
||||
accessEvents.append(key, note);
|
||||
AttributedOpEntry access = new AttributedOpEntry(mOp, false, accessEvents, null);
|
||||
int insertionPoint = discreteAccesses.size() - 1;
|
||||
@@ -10022,6 +10046,8 @@ public class AppOpsManager {
|
||||
NoteOpEvent existingAccess = accessEvents.get(key);
|
||||
if (existingAccess == null || existingAccess.getDuration() == -1) {
|
||||
accessEvents.append(key, access);
|
||||
} else if (existingAccess.mProxy == null && access.mProxy != null ) {
|
||||
existingAccess.mProxy = access.mProxy;
|
||||
}
|
||||
}
|
||||
if (reject != null) {
|
||||
|
||||
@@ -908,9 +908,32 @@ public final class PermissionManager {
|
||||
*/
|
||||
public static boolean shouldShowPackageForIndicatorCached(@NonNull Context context,
|
||||
@NonNull String packageName) {
|
||||
if (SYSTEM_PKG.equals(packageName)) {
|
||||
return false;
|
||||
return !getIndicatorExemptedPackages(context).contains(packageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of packages that are not shown by the indicators. Only a select few roles, and
|
||||
* the system app itself, are hidden. These values are updated at most every 15 seconds.
|
||||
* @hide
|
||||
*/
|
||||
public static Set<String> getIndicatorExemptedPackages(@NonNull Context context) {
|
||||
updateIndicatorExemptedPackages(context);
|
||||
ArraySet<String> pkgNames = new ArraySet<>();
|
||||
pkgNames.add(SYSTEM_PKG);
|
||||
for (int i = 0; i < INDICATOR_EXEMPTED_PACKAGES.length; i++) {
|
||||
String exemptedPackage = INDICATOR_EXEMPTED_PACKAGES[i];
|
||||
if (exemptedPackage != null) {
|
||||
pkgNames.add(exemptedPackage);
|
||||
}
|
||||
}
|
||||
return pkgNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the cached indicator exempted packages
|
||||
* @hide
|
||||
*/
|
||||
public static void updateIndicatorExemptedPackages(@NonNull Context context) {
|
||||
long now = SystemClock.elapsedRealtime();
|
||||
if (sLastIndicatorUpdateTime == -1
|
||||
|| (now - sLastIndicatorUpdateTime) > EXEMPTED_INDICATOR_ROLE_UPDATE_FREQUENCY_MS) {
|
||||
@@ -919,14 +942,6 @@ public final class PermissionManager {
|
||||
INDICATOR_EXEMPTED_PACKAGES[i] = context.getString(EXEMPTED_ROLES[i]);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < EXEMPTED_ROLES.length; i++) {
|
||||
String exemptedPackage = INDICATOR_EXEMPTED_PACKAGES[i];
|
||||
if (exemptedPackage != null && exemptedPackage.equals(packageName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Gets the list of packages that have permissions that specified
|
||||
|
||||
@@ -410,7 +410,9 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
|
||||
|
||||
int usageAttr = usage.getPackageIdHash();
|
||||
// If this usage has a proxy, but is not a proxy, it is the end of a chain.
|
||||
if (!proxies.containsKey(usageAttr) && usage.proxy != null) {
|
||||
// TODO remove once camera converted
|
||||
if (!proxies.containsKey(usageAttr) && usage.proxy != null
|
||||
&& !usage.op.equals(OPSTR_RECORD_AUDIO)) {
|
||||
proxyLabels.put(usage, new ArrayList<>());
|
||||
proxyPackages.add(usage.getPackageIdHash());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.util.function;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
/**
|
||||
* A 12-argument {@link Consumer}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface DodecConsumer<A, B, C, D, E, F, G, H, I, J, K, L> {
|
||||
void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.util.function;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A 12-argument {@link Function}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface DodecFunction<A, B, C, D, E, F, G, H, I, J, K, L, R> {
|
||||
R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.util.function;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A 12-argument {@link Predicate}
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface DodecPredicate<A, B, C, D, E, F, G, H, I, J, K, L> {
|
||||
boolean test(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l);
|
||||
}
|
||||
@@ -23,6 +23,8 @@ import android.os.Message;
|
||||
|
||||
import com.android.internal.util.function.DecConsumer;
|
||||
import com.android.internal.util.function.DecFunction;
|
||||
import com.android.internal.util.function.DodecConsumer;
|
||||
import com.android.internal.util.function.DodecFunction;
|
||||
import com.android.internal.util.function.HeptConsumer;
|
||||
import com.android.internal.util.function.HeptFunction;
|
||||
import com.android.internal.util.function.HexConsumer;
|
||||
@@ -188,7 +190,7 @@ public interface PooledLambda {
|
||||
A arg1) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,7 +207,7 @@ public interface PooledLambda {
|
||||
A arg1) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,7 +224,7 @@ public interface PooledLambda {
|
||||
A arg1) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,7 +255,7 @@ public interface PooledLambda {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
@@ -273,7 +275,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,7 +293,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,7 +311,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,7 +329,7 @@ public interface PooledLambda {
|
||||
ArgumentPlaceholder<A> arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,7 +347,7 @@ public interface PooledLambda {
|
||||
ArgumentPlaceholder<A> arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -364,7 +366,7 @@ public interface PooledLambda {
|
||||
ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -384,7 +386,7 @@ public interface PooledLambda {
|
||||
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -405,7 +407,7 @@ public interface PooledLambda {
|
||||
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4, E arg5) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 5, 1, ReturnType.BOOLEAN, arg1, arg2, arg3, arg4, arg5, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -423,7 +425,7 @@ public interface PooledLambda {
|
||||
ArgumentPlaceholder<A> arg1, B arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -441,7 +443,7 @@ public interface PooledLambda {
|
||||
A arg1, ArgumentPlaceholder<B> arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -459,7 +461,7 @@ public interface PooledLambda {
|
||||
A arg1, ArgumentPlaceholder<B> arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -477,7 +479,7 @@ public interface PooledLambda {
|
||||
A arg1, ArgumentPlaceholder<B> arg2) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,7 +511,7 @@ public interface PooledLambda {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
@@ -530,7 +532,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -549,7 +551,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -568,7 +570,7 @@ public interface PooledLambda {
|
||||
ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -587,7 +589,7 @@ public interface PooledLambda {
|
||||
ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -606,7 +608,7 @@ public interface PooledLambda {
|
||||
A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -625,7 +627,7 @@ public interface PooledLambda {
|
||||
A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -644,7 +646,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -663,7 +665,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -696,7 +698,7 @@ public interface PooledLambda {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
@@ -718,7 +720,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -738,7 +740,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -758,7 +760,7 @@ public interface PooledLambda {
|
||||
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -778,7 +780,7 @@ public interface PooledLambda {
|
||||
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -798,7 +800,7 @@ public interface PooledLambda {
|
||||
A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -818,7 +820,7 @@ public interface PooledLambda {
|
||||
A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -838,7 +840,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -858,7 +860,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -878,7 +880,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -898,7 +900,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -932,7 +934,7 @@ public interface PooledLambda {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
@@ -955,7 +957,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3, D arg4, E arg5) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -976,7 +978,7 @@ public interface PooledLambda {
|
||||
function, A arg1, B arg2, C arg3, D arg4, E arg5) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1012,7 +1014,7 @@ public interface PooledLambda {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
@@ -1036,7 +1038,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1058,7 +1060,7 @@ public interface PooledLambda {
|
||||
? extends R> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1095,7 +1097,7 @@ public interface PooledLambda {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
@@ -1120,7 +1122,7 @@ public interface PooledLambda {
|
||||
? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1144,7 +1146,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1182,7 +1184,7 @@ public interface PooledLambda {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
@@ -1209,7 +1211,7 @@ public interface PooledLambda {
|
||||
H arg8) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1234,7 +1236,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 8, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1274,7 +1276,7 @@ public interface PooledLambda {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
null, null, null);
|
||||
null, null, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
@@ -1302,7 +1304,7 @@ public interface PooledLambda {
|
||||
E arg5, F arg6, G arg7, H arg8, I arg9) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
arg9, null, null);
|
||||
arg9, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1328,7 +1330,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 9, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
arg9, null, null);
|
||||
arg9, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1369,7 +1371,7 @@ public interface PooledLambda {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
arg9, null, null);
|
||||
arg9, null, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
@@ -1398,7 +1400,7 @@ public interface PooledLambda {
|
||||
D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 10, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
arg9, arg10, null);
|
||||
arg9, arg10, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1425,7 +1427,7 @@ public interface PooledLambda {
|
||||
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 10, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
arg9, arg10, null);
|
||||
arg9, arg10, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1467,7 +1469,7 @@ public interface PooledLambda {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 10, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
|
||||
arg8, arg9, arg10, null);
|
||||
arg8, arg9, arg10, null, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
@@ -1498,7 +1500,7 @@ public interface PooledLambda {
|
||||
C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10, K arg11) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 11, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
arg9, arg10, arg11);
|
||||
arg9, arg10, arg11, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1528,7 +1530,7 @@ public interface PooledLambda {
|
||||
K arg11) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 11, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
arg9, arg10, arg11);
|
||||
arg9, arg10, arg11, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1571,7 +1573,118 @@ public interface PooledLambda {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 11, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
|
||||
arg8, arg9, arg10, arg11);
|
||||
arg8, arg9, arg10, arg11, null);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledRunnable} factory
|
||||
*
|
||||
* @param function non-capturing lambda(typically an unbounded method reference)
|
||||
* to be invoked on call
|
||||
* @param arg1 parameter supplied to {@code function} on call
|
||||
* @param arg2 parameter supplied to {@code function} on call
|
||||
* @param arg3 parameter supplied to {@code function} on call
|
||||
* @param arg4 parameter supplied to {@code function} on call
|
||||
* @param arg5 parameter supplied to {@code function} on call
|
||||
* @param arg6 parameter supplied to {@code function} on call
|
||||
* @param arg7 parameter supplied to {@code function} on call
|
||||
* @param arg8 parameter supplied to {@code function} on call
|
||||
* @param arg9 parameter supplied to {@code function} on call
|
||||
* @param arg10 parameter supplied to {@code function} on call
|
||||
* @param arg11 parameter supplied to {@code function} on call
|
||||
* @param arg12 parameter supplied to {@code function} on call
|
||||
* @return a {@link PooledRunnable}, equivalent to lambda:
|
||||
* {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
|
||||
* arg11, arg12) }
|
||||
*/
|
||||
static <A, B, C, D, E, F, G, H, I, J, K, L> PooledRunnable obtainRunnable(
|
||||
DodecConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
|
||||
? super G, ? super H, ? super I, ? super J, ? super K,
|
||||
? super L> function,
|
||||
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10,
|
||||
K arg11, L arg12) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 12, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
arg9, arg10, arg11, arg12);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PooledSupplier} factory
|
||||
*
|
||||
* @param function non-capturing lambda(typically an unbounded method reference)
|
||||
* to be invoked on call
|
||||
* @param arg1 parameter supplied to {@code function} on call
|
||||
* @param arg2 parameter supplied to {@code function} on call
|
||||
* @param arg3 parameter supplied to {@code function} on call
|
||||
* @param arg4 parameter supplied to {@code function} on call
|
||||
* @param arg5 parameter supplied to {@code function} on call
|
||||
* @param arg6 parameter supplied to {@code function} on call
|
||||
* @param arg7 parameter supplied to {@code function} on call
|
||||
* @param arg8 parameter supplied to {@code function} on call
|
||||
* @param arg9 parameter supplied to {@code function} on call
|
||||
* @param arg10 parameter supplied to {@code function} on call
|
||||
* @param arg11 parameter supplied to {@code function} on call
|
||||
* @param arg12 parameter supplied to {@code function} on call
|
||||
* @return a {@link PooledSupplier}, equivalent to lambda:
|
||||
* {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10,
|
||||
* arg11) }
|
||||
*/
|
||||
static <A, B, C, D, E, F, G, H, I, J, K, L, R> PooledSupplier<R> obtainSupplier(
|
||||
DodecFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
|
||||
? super G, ? super H, ? super I, ? super J, ? super K, ? extends L,
|
||||
? extends R> function,
|
||||
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10,
|
||||
K arg11, L arg12) {
|
||||
return acquire(PooledLambdaImpl.sPool,
|
||||
function, 11, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
|
||||
arg9, arg10, arg11, arg12);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory of {@link Message}s that contain an
|
||||
* ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
|
||||
* {@link Message#getCallback internal callback}.
|
||||
*
|
||||
* The callback is equivalent to one obtainable via
|
||||
* {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
|
||||
*
|
||||
* Note that using this method with {@link android.os.Handler#handleMessage}
|
||||
* is more efficient than the alternative of {@link android.os.Handler#post}
|
||||
* with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
|
||||
* when obtaining {@link Message} and {@link PooledRunnable} from pools separately
|
||||
*
|
||||
* You may optionally set a {@link Message#what} for the message if you want to be
|
||||
* able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
|
||||
* there's no need to do so
|
||||
*
|
||||
* @param function non-capturing lambda(typically an unbounded method reference)
|
||||
* to be invoked on call
|
||||
* @param arg1 parameter supplied to {@code function} on call
|
||||
* @param arg2 parameter supplied to {@code function} on call
|
||||
* @param arg3 parameter supplied to {@code function} on call
|
||||
* @param arg4 parameter supplied to {@code function} on call
|
||||
* @param arg5 parameter supplied to {@code function} on call
|
||||
* @param arg6 parameter supplied to {@code function} on call
|
||||
* @param arg7 parameter supplied to {@code function} on call
|
||||
* @param arg8 parameter supplied to {@code function} on call
|
||||
* @param arg9 parameter supplied to {@code function} on call
|
||||
* @param arg10 parameter supplied to {@code function} on call
|
||||
* @param arg11 parameter supplied to {@code function} on call
|
||||
* @param arg12 parameter supplied to {@code function} on call
|
||||
* @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
|
||||
* arg7, arg8, arg9, arg10, arg11) } when handled
|
||||
*/
|
||||
static <A, B, C, D, E, F, G, H, I, J, K, L> Message obtainMessage(
|
||||
DodecConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
|
||||
? super G, ? super H, ? super I, ? super J, ? super K, ? super L> function,
|
||||
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9, J arg10,
|
||||
K arg11, L arg12) {
|
||||
synchronized (Message.sPoolSync) {
|
||||
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
|
||||
function, 11, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
|
||||
arg8, arg9, arg10, arg11, arg12);
|
||||
return Message.obtain().setCallback(callback.recycleOnUse());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ import com.android.internal.util.FunctionalUtils;
|
||||
import com.android.internal.util.function.DecConsumer;
|
||||
import com.android.internal.util.function.DecFunction;
|
||||
import com.android.internal.util.function.DecPredicate;
|
||||
import com.android.internal.util.function.DodecConsumer;
|
||||
import com.android.internal.util.function.DodecFunction;
|
||||
import com.android.internal.util.function.DodecPredicate;
|
||||
import com.android.internal.util.function.HeptConsumer;
|
||||
import com.android.internal.util.function.HeptFunction;
|
||||
import com.android.internal.util.function.HeptPredicate;
|
||||
@@ -458,6 +461,28 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case 12: {
|
||||
switch (returnType) {
|
||||
case LambdaType.ReturnType.VOID: {
|
||||
((DodecConsumer) mFunc).accept(popArg(0), popArg(1),
|
||||
popArg(2), popArg(3), popArg(4), popArg(5),
|
||||
popArg(6), popArg(7), popArg(8), popArg(9), popArg(10), popArg(11));
|
||||
return null;
|
||||
}
|
||||
case LambdaType.ReturnType.BOOLEAN: {
|
||||
return (R) (Object) ((DodecPredicate) mFunc).test(popArg(0),
|
||||
popArg(1), popArg(2), popArg(3), popArg(4),
|
||||
popArg(5), popArg(6), popArg(7), popArg(8), popArg(9), popArg(10),
|
||||
popArg(11));
|
||||
}
|
||||
case LambdaType.ReturnType.OBJECT: {
|
||||
return (R) ((DodecFunction) mFunc).apply(popArg(0), popArg(1),
|
||||
popArg(2), popArg(3), popArg(4), popArg(5),
|
||||
popArg(6), popArg(7), popArg(8), popArg(9), popArg(10), popArg(11));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
throw new IllegalStateException("Unknown function type: " + LambdaType.toString(funcType));
|
||||
}
|
||||
@@ -523,7 +548,8 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
|
||||
*/
|
||||
static <E extends PooledLambda> E acquire(Pool pool, Object func,
|
||||
int fNumArgs, int numPlaceholders, int fReturnType, Object a, Object b, Object c,
|
||||
Object d, Object e, Object f, Object g, Object h, Object i, Object j, Object k) {
|
||||
Object d, Object e, Object f, Object g, Object h, Object i, Object j, Object k,
|
||||
Object l) {
|
||||
PooledLambdaImpl r = acquire(pool);
|
||||
if (DEBUG) {
|
||||
Log.i(LOG_TAG,
|
||||
@@ -543,6 +569,7 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
|
||||
+ ", i = " + i
|
||||
+ ", j = " + j
|
||||
+ ", k = " + k
|
||||
+ ", l = " + l
|
||||
+ ")");
|
||||
}
|
||||
r.mFunc = Objects.requireNonNull(func);
|
||||
@@ -560,6 +587,7 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
|
||||
setIfInBounds(r.mArgs, 8, i);
|
||||
setIfInBounds(r.mArgs, 9, j);
|
||||
setIfInBounds(r.mArgs, 10, k);
|
||||
setIfInBounds(r.mArgs, 11, l);
|
||||
return (E) r;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,13 @@ package com.android.server.appop;
|
||||
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
|
||||
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
|
||||
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
|
||||
import static android.app.AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
|
||||
import static android.app.AppOpsManager.CALL_BACK_ON_SWITCHED_OP;
|
||||
import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG;
|
||||
import static android.app.AppOpsManager.FILTER_BY_OP_NAMES;
|
||||
import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME;
|
||||
import static android.app.AppOpsManager.FILTER_BY_UID;
|
||||
import static android.app.AppOpsManager.HISTORY_FLAG_GET_ATTRIBUTION_CHAINS;
|
||||
import static android.app.AppOpsManager.HistoricalOpsRequestFilter;
|
||||
import static android.app.AppOpsManager.KEY_BG_STATE_SETTLE_TIME;
|
||||
import static android.app.AppOpsManager.KEY_FG_SERVICE_STATE_SETTLE_TIME;
|
||||
@@ -130,6 +132,7 @@ import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.os.storage.StorageManagerInternal;
|
||||
import android.permission.PermissionManager;
|
||||
import android.provider.Settings;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
@@ -200,8 +203,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class AppOpsService extends IAppOpsService.Stub {
|
||||
@@ -2357,10 +2360,21 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
final String[] opNamesArray = (opNames != null)
|
||||
? opNames.toArray(new String[opNames.size()]) : null;
|
||||
|
||||
Set<String> attributionChainExemptPackages = null;
|
||||
if ((dataType & HISTORY_FLAG_GET_ATTRIBUTION_CHAINS) != 0) {
|
||||
attributionChainExemptPackages =
|
||||
PermissionManager.getIndicatorExemptedPackages(mContext);
|
||||
}
|
||||
|
||||
final String[] chainExemptPkgArray = attributionChainExemptPackages != null
|
||||
? attributionChainExemptPackages.toArray(
|
||||
new String[attributionChainExemptPackages.size()]) : null;
|
||||
|
||||
// Must not hold the appops lock
|
||||
mHandler.post(PooledLambda.obtainRunnable(HistoricalRegistry::getHistoricalOps,
|
||||
mHistoricalRegistry, uid, packageName, attributionTag, opNamesArray, dataType,
|
||||
filter, beginTimeMillis, endTimeMillis, flags, callback).recycleOnUse());
|
||||
filter, beginTimeMillis, endTimeMillis, flags, chainExemptPkgArray,
|
||||
callback).recycleOnUse());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2377,10 +2391,21 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
final String[] opNamesArray = (opNames != null)
|
||||
? opNames.toArray(new String[opNames.size()]) : null;
|
||||
|
||||
Set<String> attributionChainExemptPackages = null;
|
||||
if ((dataType & HISTORY_FLAG_GET_ATTRIBUTION_CHAINS) != 0) {
|
||||
attributionChainExemptPackages =
|
||||
PermissionManager.getIndicatorExemptedPackages(mContext);
|
||||
}
|
||||
|
||||
final String[] chainExemptPkgArray = attributionChainExemptPackages != null
|
||||
? attributionChainExemptPackages.toArray(
|
||||
new String[attributionChainExemptPackages.size()]) : null;
|
||||
|
||||
// Must not hold the appops lock
|
||||
mHandler.post(PooledLambda.obtainRunnable(HistoricalRegistry::getHistoricalOpsFromDiskRaw,
|
||||
mHistoricalRegistry, uid, packageName, attributionTag, opNamesArray, dataType,
|
||||
filter, beginTimeMillis, endTimeMillis, flags, callback).recycleOnUse());
|
||||
filter, beginTimeMillis, endTimeMillis, flags, chainExemptPkgArray,
|
||||
callback).recycleOnUse());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3838,7 +3863,8 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
final boolean isSelfBlame = Binder.getCallingUid() == proxiedUid;
|
||||
final boolean isProxyTrusted = mContext.checkPermission(
|
||||
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
|
||||
== PackageManager.PERMISSION_GRANTED || isSelfBlame;
|
||||
== PackageManager.PERMISSION_GRANTED || isSelfBlame
|
||||
|| attributionChainId != ATTRIBUTION_CHAIN_ID_NONE;
|
||||
|
||||
String resolvedProxiedPackageName = AppOpsManager.resolvePackageName(proxiedUid,
|
||||
proxiedPackageName);
|
||||
@@ -5174,8 +5200,6 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
}
|
||||
|
||||
static class Shell extends ShellCommand {
|
||||
static final AtomicInteger sAttributionChainIds = new AtomicInteger(0);
|
||||
|
||||
final IAppOpsService mInterface;
|
||||
final AppOpsService mInternal;
|
||||
|
||||
@@ -5645,8 +5669,7 @@ public class AppOpsService extends IAppOpsService.Stub {
|
||||
shell.mInterface.startOperation(shell.mToken, shell.op, shell.packageUid,
|
||||
shell.packageName, shell.attributionTag, true, true,
|
||||
"appops start shell command", true,
|
||||
AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR,
|
||||
shell.sAttributionChainIds.incrementAndGet());
|
||||
AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR, ATTRIBUTION_CHAIN_ID_NONE);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.android.server.appop;
|
||||
|
||||
import static android.app.AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
|
||||
import static android.app.AppOpsManager.ATTRIBUTION_FLAG_ACCESSOR;
|
||||
import static android.app.AppOpsManager.ATTRIBUTION_FLAG_RECEIVER;
|
||||
import static android.app.AppOpsManager.FILTER_BY_ATTRIBUTION_TAG;
|
||||
import static android.app.AppOpsManager.FILTER_BY_OP_NAMES;
|
||||
import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME;
|
||||
@@ -72,6 +74,8 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class manages information about recent accesses to ops for permission usage timeline.
|
||||
@@ -270,13 +274,19 @@ final class DiscreteRegistry {
|
||||
long beginTimeMillis, long endTimeMillis,
|
||||
@AppOpsManager.HistoricalOpsRequestFilter int filter, int uidFilter,
|
||||
@Nullable String packageNameFilter, @Nullable String[] opNamesFilter,
|
||||
@Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter) {
|
||||
@Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter,
|
||||
Set<String> attributionExemptPkgs) {
|
||||
boolean assembleChains = attributionExemptPkgs != null;
|
||||
DiscreteOps discreteOps = getAllDiscreteOps();
|
||||
ArrayMap<Integer, AttributionChain> attributionChains = new ArrayMap<>();
|
||||
if (assembleChains) {
|
||||
attributionChains = createAttributionChains(discreteOps, attributionExemptPkgs);
|
||||
}
|
||||
beginTimeMillis = max(beginTimeMillis, Instant.now().minus(sDiscreteHistoryCutoff,
|
||||
ChronoUnit.MILLIS).toEpochMilli());
|
||||
discreteOps.filter(beginTimeMillis, endTimeMillis, filter, uidFilter, packageNameFilter,
|
||||
opNamesFilter, attributionTagFilter, flagsFilter);
|
||||
discreteOps.applyToHistoricalOps(result);
|
||||
opNamesFilter, attributionTagFilter, flagsFilter, attributionChains);
|
||||
discreteOps.applyToHistoricalOps(result, attributionChains);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -317,13 +327,56 @@ final class DiscreteRegistry {
|
||||
} finally {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) { }
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayMap<Integer, AttributionChain> createAttributionChains(
|
||||
DiscreteOps discreteOps, Set<String> attributionExemptPkgs) {
|
||||
ArrayMap<Integer, AttributionChain> chains = new ArrayMap<>();
|
||||
int nUids = discreteOps.mUids.size();
|
||||
for (int uidNum = 0; uidNum < nUids; uidNum++) {
|
||||
ArrayMap<String, DiscretePackageOps> pkgs = discreteOps.mUids.valueAt(uidNum).mPackages;
|
||||
int uid = discreteOps.mUids.keyAt(uidNum);
|
||||
int nPackages = pkgs.size();
|
||||
for (int pkgNum = 0; pkgNum < nPackages; pkgNum++) {
|
||||
ArrayMap<Integer, DiscreteOp> ops = pkgs.valueAt(pkgNum).mPackageOps;
|
||||
String pkg = pkgs.keyAt(pkgNum);
|
||||
int nOps = ops.size();
|
||||
for (int opNum = 0; opNum < nOps; opNum++) {
|
||||
ArrayMap<String, List<DiscreteOpEvent>> attrOps =
|
||||
ops.valueAt(opNum).mAttributedOps;
|
||||
int op = ops.keyAt(opNum);
|
||||
int nAttrOps = attrOps.size();
|
||||
for (int attrOpNum = 0; attrOpNum < nAttrOps; attrOpNum++) {
|
||||
List<DiscreteOpEvent> opEvents = attrOps.valueAt(attrOpNum);
|
||||
String attributionTag = attrOps.keyAt(attrOpNum);
|
||||
int nOpEvents = opEvents.size();
|
||||
for (int opEventNum = 0; opEventNum < nOpEvents; opEventNum++) {
|
||||
DiscreteOpEvent event = opEvents.get(opEventNum);
|
||||
if (event == null
|
||||
|| event.mAttributionChainId == ATTRIBUTION_CHAIN_ID_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!chains.containsKey(event.mAttributionChainId)) {
|
||||
chains.put(event.mAttributionChainId,
|
||||
new AttributionChain(attributionExemptPkgs));
|
||||
}
|
||||
chains.get(event.mAttributionChainId)
|
||||
.addEvent(pkg, uid, attributionTag, op, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return chains;
|
||||
}
|
||||
|
||||
private void readDiscreteOpsFromDisk(DiscreteOps discreteOps) {
|
||||
synchronized (mOnDiskLock) {
|
||||
long beginTimeMillis = Instant.now().minus(sDiscreteHistoryCutoff,
|
||||
@@ -389,7 +442,7 @@ final class DiscreteRegistry {
|
||||
String[] opNamesFilter = dumpOp == OP_NONE ? null
|
||||
: new String[]{AppOpsManager.opToPublicName(dumpOp)};
|
||||
discreteOps.filter(0, Instant.now().toEpochMilli(), filter, uidFilter, packageNameFilter,
|
||||
opNamesFilter, attributionTagFilter, OP_FLAGS_ALL);
|
||||
opNamesFilter, attributionTagFilter, OP_FLAGS_ALL, new ArrayMap<>());
|
||||
pw.print(prefix);
|
||||
pw.print("Largest chain id: ");
|
||||
pw.print(mDiscreteOps.mLargestChainId);
|
||||
@@ -419,6 +472,134 @@ final class DiscreteRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a chain of usages, each attributing its usage to the one before it
|
||||
*/
|
||||
private static final class AttributionChain {
|
||||
private static final class OpEvent {
|
||||
String mPkgName;
|
||||
int mUid;
|
||||
String mAttributionTag;
|
||||
int mOpCode;
|
||||
DiscreteOpEvent mOpEvent;
|
||||
|
||||
OpEvent(String pkgName, int uid, String attributionTag, int opCode,
|
||||
DiscreteOpEvent event) {
|
||||
mPkgName = pkgName;
|
||||
mUid = uid;
|
||||
mAttributionTag = attributionTag;
|
||||
mOpCode = opCode;
|
||||
mOpEvent = event;
|
||||
}
|
||||
|
||||
public boolean matches(String pkgName, int uid, String attributionTag, int opCode,
|
||||
DiscreteOpEvent event) {
|
||||
return Objects.equals(pkgName, mPkgName) && mUid == uid
|
||||
&& Objects.equals(attributionTag, mAttributionTag) && mOpCode == opCode
|
||||
&& mOpEvent.mAttributionChainId == event.mAttributionChainId
|
||||
&& mOpEvent.mAttributionFlags == event.mAttributionFlags
|
||||
&& mOpEvent.mNoteTime == event.mNoteTime;
|
||||
}
|
||||
|
||||
public boolean packageOpEquals(OpEvent other) {
|
||||
return Objects.equals(other.mPkgName, mPkgName) && other.mUid == mUid
|
||||
&& Objects.equals(other.mAttributionTag, mAttributionTag)
|
||||
&& mOpCode == other.mOpCode;
|
||||
}
|
||||
|
||||
public boolean equalsExceptDuration(OpEvent other) {
|
||||
if (other.mOpEvent.mNoteDuration == mOpEvent.mNoteDuration) {
|
||||
return false;
|
||||
}
|
||||
return packageOpEquals(other) && mOpEvent.equalsExceptDuration(other.mOpEvent);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<OpEvent> mChain = new ArrayList<>();
|
||||
Set<String> mExemptPkgs;
|
||||
OpEvent mStartEvent = null;
|
||||
OpEvent mLastVisibleEvent = null;
|
||||
|
||||
AttributionChain(Set<String> exemptPkgs) {
|
||||
mExemptPkgs = exemptPkgs;
|
||||
}
|
||||
|
||||
boolean isComplete() {
|
||||
return !mChain.isEmpty() && getStart() != null && isEnd(mChain.get(mChain.size() - 1));
|
||||
}
|
||||
|
||||
boolean isStart(String pkgName, int uid, String attributionTag, int op,
|
||||
DiscreteOpEvent opEvent) {
|
||||
if (mStartEvent == null || opEvent == null) {
|
||||
return false;
|
||||
}
|
||||
return mStartEvent.matches(pkgName, uid, attributionTag, op, opEvent);
|
||||
}
|
||||
|
||||
private OpEvent getStart() {
|
||||
return mChain.isEmpty() || !isStart(mChain.get(0)) ? null : mChain.get(0);
|
||||
}
|
||||
|
||||
private OpEvent getLastVisible() {
|
||||
// Search all nodes but the first one, which is the start node
|
||||
for (int i = mChain.size() - 1; i > 0; i++) {
|
||||
OpEvent event = mChain.get(i);
|
||||
if (!mExemptPkgs.contains(event.mPkgName)) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void addEvent(String pkgName, int uid, String attributionTag, int op,
|
||||
DiscreteOpEvent opEvent) {
|
||||
OpEvent event = new OpEvent(pkgName, uid, attributionTag, op, opEvent);
|
||||
|
||||
// check if we have a matching event, without duration, replacing duration otherwise
|
||||
for (int i = 0; i < mChain.size(); i++) {
|
||||
OpEvent item = mChain.get(i);
|
||||
if (item.equalsExceptDuration(event)) {
|
||||
if (event.mOpEvent.mNoteDuration != -1) {
|
||||
item.mOpEvent = event.mOpEvent;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mChain.isEmpty() || isEnd(event)) {
|
||||
mChain.add(event);
|
||||
} else if (isStart(event)) {
|
||||
mChain.add(0, event);
|
||||
|
||||
} else {
|
||||
for (int i = 0; i < mChain.size(); i++) {
|
||||
OpEvent currEvent = mChain.get(i);
|
||||
if ((!isStart(currEvent)
|
||||
&& currEvent.mOpEvent.mNoteTime > event.mOpEvent.mNoteTime)
|
||||
|| i == mChain.size() - 1 && isEnd(currEvent)) {
|
||||
mChain.add(i, event);
|
||||
break;
|
||||
} else if (i == mChain.size() - 1) {
|
||||
mChain.add(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mStartEvent = isComplete() ? getStart() : null;
|
||||
mLastVisibleEvent = isComplete() ? getLastVisible() : null;
|
||||
}
|
||||
|
||||
private boolean isEnd(OpEvent event) {
|
||||
return event != null
|
||||
&& (event.mOpEvent.mAttributionFlags & ATTRIBUTION_FLAG_ACCESSOR) != 0;
|
||||
}
|
||||
|
||||
private boolean isStart(OpEvent event) {
|
||||
return event != null
|
||||
&& (event.mOpEvent.mAttributionFlags & ATTRIBUTION_FLAG_RECEIVER) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
private final class DiscreteOps {
|
||||
ArrayMap<Integer, DiscreteUidOps> mUids;
|
||||
int mChainIdOffset;
|
||||
@@ -448,25 +629,27 @@ final class DiscreteRegistry {
|
||||
@Nullable String attributionTag, @AppOpsManager.OpFlags int flags,
|
||||
@AppOpsManager.UidState int uidState, long accessTime, long accessDuration,
|
||||
@AppOpsManager.AttributionFlags int attributionFlags, int attributionChainId) {
|
||||
int offsetChainId = attributionChainId;
|
||||
if (attributionChainId != ATTRIBUTION_CHAIN_ID_NONE) {
|
||||
attributionChainId += mChainIdOffset;
|
||||
if (attributionChainId < 0) {
|
||||
attributionChainId -= mChainIdOffset;
|
||||
mChainIdOffset = 0;
|
||||
mLargestChainId = attributionChainId;
|
||||
}
|
||||
if (attributionChainId > mLargestChainId) {
|
||||
mLargestChainId = attributionChainId;
|
||||
offsetChainId = attributionChainId + mChainIdOffset;
|
||||
if (offsetChainId > mLargestChainId) {
|
||||
mLargestChainId = offsetChainId;
|
||||
} else if (offsetChainId < 0) {
|
||||
// handle overflow
|
||||
offsetChainId = 0;
|
||||
mLargestChainId = 0;
|
||||
mChainIdOffset = -1 * attributionChainId;
|
||||
}
|
||||
}
|
||||
getOrCreateDiscreteUidOps(uid).addDiscreteAccess(op, packageName, attributionTag, flags,
|
||||
uidState, accessTime, accessDuration, attributionFlags, attributionChainId);
|
||||
uidState, accessTime, accessDuration, attributionFlags, offsetChainId);
|
||||
}
|
||||
|
||||
private void filter(long beginTimeMillis, long endTimeMillis,
|
||||
@AppOpsManager.HistoricalOpsRequestFilter int filter, int uidFilter,
|
||||
@Nullable String packageNameFilter, @Nullable String[] opNamesFilter,
|
||||
@Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter) {
|
||||
@Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter,
|
||||
ArrayMap<Integer, AttributionChain> attributionChains) {
|
||||
if ((filter & FILTER_BY_UID) != 0) {
|
||||
ArrayMap<Integer, DiscreteUidOps> uids = new ArrayMap<>();
|
||||
uids.put(uidFilter, getOrCreateDiscreteUidOps(uidFilter));
|
||||
@@ -475,7 +658,8 @@ final class DiscreteRegistry {
|
||||
int nUids = mUids.size();
|
||||
for (int i = nUids - 1; i >= 0; i--) {
|
||||
mUids.valueAt(i).filter(beginTimeMillis, endTimeMillis, filter, packageNameFilter,
|
||||
opNamesFilter, attributionTagFilter, flagsFilter);
|
||||
opNamesFilter, attributionTagFilter, flagsFilter, mUids.keyAt(i),
|
||||
attributionChains);
|
||||
if (mUids.valueAt(i).isEmpty()) {
|
||||
mUids.removeAt(i);
|
||||
}
|
||||
@@ -498,10 +682,11 @@ final class DiscreteRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
private void applyToHistoricalOps(AppOpsManager.HistoricalOps result) {
|
||||
private void applyToHistoricalOps(AppOpsManager.HistoricalOps result,
|
||||
ArrayMap<Integer, AttributionChain> attributionChains) {
|
||||
int nUids = mUids.size();
|
||||
for (int i = 0; i < nUids; i++) {
|
||||
mUids.valueAt(i).applyToHistory(result, mUids.keyAt(i));
|
||||
mUids.valueAt(i).applyToHistory(result, mUids.keyAt(i), attributionChains);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -668,7 +853,8 @@ final class DiscreteRegistry {
|
||||
private void filter(long beginTimeMillis, long endTimeMillis,
|
||||
@AppOpsManager.HistoricalOpsRequestFilter int filter,
|
||||
@Nullable String packageNameFilter, @Nullable String[] opNamesFilter,
|
||||
@Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter) {
|
||||
@Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter,
|
||||
int currentUid, ArrayMap<Integer, AttributionChain> attributionChains) {
|
||||
if ((filter & FILTER_BY_PACKAGE_NAME) != 0) {
|
||||
ArrayMap<String, DiscretePackageOps> packages = new ArrayMap<>();
|
||||
packages.put(packageNameFilter, getOrCreateDiscretePackageOps(packageNameFilter));
|
||||
@@ -677,7 +863,8 @@ final class DiscreteRegistry {
|
||||
int nPackages = mPackages.size();
|
||||
for (int i = nPackages - 1; i >= 0; i--) {
|
||||
mPackages.valueAt(i).filter(beginTimeMillis, endTimeMillis, filter, opNamesFilter,
|
||||
attributionTagFilter, flagsFilter);
|
||||
attributionTagFilter, flagsFilter, currentUid, mPackages.keyAt(i),
|
||||
attributionChains);
|
||||
if (mPackages.valueAt(i).isEmpty()) {
|
||||
mPackages.removeAt(i);
|
||||
}
|
||||
@@ -712,10 +899,12 @@ final class DiscreteRegistry {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void applyToHistory(AppOpsManager.HistoricalOps result, int uid) {
|
||||
private void applyToHistory(AppOpsManager.HistoricalOps result, int uid,
|
||||
@NonNull ArrayMap<Integer, AttributionChain> attributionChains) {
|
||||
int nPackages = mPackages.size();
|
||||
for (int i = 0; i < nPackages; i++) {
|
||||
mPackages.valueAt(i).applyToHistory(result, uid, mPackages.keyAt(i));
|
||||
mPackages.valueAt(i).applyToHistory(result, uid, mPackages.keyAt(i),
|
||||
attributionChains);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,7 +972,8 @@ final class DiscreteRegistry {
|
||||
private void filter(long beginTimeMillis, long endTimeMillis,
|
||||
@AppOpsManager.HistoricalOpsRequestFilter int filter,
|
||||
@Nullable String[] opNamesFilter, @Nullable String attributionTagFilter,
|
||||
@AppOpsManager.OpFlags int flagsFilter) {
|
||||
@AppOpsManager.OpFlags int flagsFilter, int currentUid, String currentPkgName,
|
||||
ArrayMap<Integer, AttributionChain> attributionChains) {
|
||||
int nOps = mPackageOps.size();
|
||||
for (int i = nOps - 1; i >= 0; i--) {
|
||||
int opId = mPackageOps.keyAt(i);
|
||||
@@ -793,7 +983,8 @@ final class DiscreteRegistry {
|
||||
continue;
|
||||
}
|
||||
mPackageOps.valueAt(i).filter(beginTimeMillis, endTimeMillis, filter,
|
||||
attributionTagFilter, flagsFilter);
|
||||
attributionTagFilter, flagsFilter, currentUid, currentPkgName,
|
||||
mPackageOps.keyAt(i), attributionChains);
|
||||
if (mPackageOps.valueAt(i).isEmpty()) {
|
||||
mPackageOps.removeAt(i);
|
||||
}
|
||||
@@ -817,11 +1008,12 @@ final class DiscreteRegistry {
|
||||
}
|
||||
|
||||
private void applyToHistory(AppOpsManager.HistoricalOps result, int uid,
|
||||
@NonNull String packageName) {
|
||||
@NonNull String packageName,
|
||||
@NonNull ArrayMap<Integer, AttributionChain> attributionChains) {
|
||||
int nPackageOps = mPackageOps.size();
|
||||
for (int i = 0; i < nPackageOps; i++) {
|
||||
mPackageOps.valueAt(i).applyToHistory(result, uid, packageName,
|
||||
mPackageOps.keyAt(i));
|
||||
mPackageOps.keyAt(i), attributionChains);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -880,7 +1072,9 @@ final class DiscreteRegistry {
|
||||
|
||||
private void filter(long beginTimeMillis, long endTimeMillis,
|
||||
@AppOpsManager.HistoricalOpsRequestFilter int filter,
|
||||
@Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter) {
|
||||
@Nullable String attributionTagFilter, @AppOpsManager.OpFlags int flagsFilter,
|
||||
int currentUid, String currentPkgName, int currentOp,
|
||||
ArrayMap<Integer, AttributionChain> attributionChains) {
|
||||
if ((filter & FILTER_BY_ATTRIBUTION_TAG) != 0) {
|
||||
ArrayMap<String, List<DiscreteOpEvent>> attributedOps = new ArrayMap<>();
|
||||
attributedOps.put(attributionTagFilter,
|
||||
@@ -892,7 +1086,9 @@ final class DiscreteRegistry {
|
||||
for (int i = nTags - 1; i >= 0; i--) {
|
||||
String tag = mAttributedOps.keyAt(i);
|
||||
List<DiscreteOpEvent> list = mAttributedOps.valueAt(i);
|
||||
list = filterEventsList(list, beginTimeMillis, endTimeMillis, flagsFilter);
|
||||
list = filterEventsList(list, beginTimeMillis, endTimeMillis, flagsFilter,
|
||||
currentUid, currentPkgName, currentOp, mAttributedOps.keyAt(i),
|
||||
attributionChains);
|
||||
mAttributedOps.put(tag, list);
|
||||
if (list.size() == 0) {
|
||||
mAttributedOps.removeAt(i);
|
||||
@@ -954,7 +1150,8 @@ final class DiscreteRegistry {
|
||||
}
|
||||
|
||||
private void applyToHistory(AppOpsManager.HistoricalOps result, int uid,
|
||||
@NonNull String packageName, int op) {
|
||||
@NonNull String packageName, int op,
|
||||
@NonNull ArrayMap<Integer, AttributionChain> attributionChains) {
|
||||
int nOps = mAttributedOps.size();
|
||||
for (int i = 0; i < nOps; i++) {
|
||||
String tag = mAttributedOps.keyAt(i);
|
||||
@@ -962,9 +1159,21 @@ final class DiscreteRegistry {
|
||||
int nEvents = events.size();
|
||||
for (int j = 0; j < nEvents; j++) {
|
||||
DiscreteOpEvent event = events.get(j);
|
||||
AppOpsManager.OpEventProxyInfo proxy = null;
|
||||
if (event.mAttributionChainId != ATTRIBUTION_CHAIN_ID_NONE
|
||||
&& attributionChains != null) {
|
||||
AttributionChain chain = attributionChains.get(event.mAttributionChainId);
|
||||
if (chain != null && chain.isComplete()
|
||||
&& chain.isStart(packageName, uid, tag, op, event)
|
||||
&& chain.mLastVisibleEvent != null) {
|
||||
AttributionChain.OpEvent proxyEvent = chain.mLastVisibleEvent;
|
||||
proxy = new AppOpsManager.OpEventProxyInfo(proxyEvent.mUid,
|
||||
proxyEvent.mPkgName, proxyEvent.mAttributionTag);
|
||||
}
|
||||
}
|
||||
result.addDiscreteAccess(op, uid, packageName, tag, event.mUidState,
|
||||
event.mOpFlag, discretizeTimeStamp(event.mNoteTime),
|
||||
discretizeDuration(event.mNoteDuration));
|
||||
discretizeDuration(event.mNoteDuration), proxy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1059,6 +1268,13 @@ final class DiscreteRegistry {
|
||||
mAttributionChainId = attributionChainId;
|
||||
}
|
||||
|
||||
public boolean equalsExceptDuration(DiscreteOpEvent o) {
|
||||
return mNoteTime == o.mNoteTime && mUidState == o.mUidState && mOpFlag == o.mOpFlag
|
||||
&& mAttributionFlags == o.mAttributionFlags
|
||||
&& mAttributionChainId == o.mAttributionChainId;
|
||||
|
||||
}
|
||||
|
||||
private void dump(@NonNull PrintWriter pw, @NonNull SimpleDateFormat sdf,
|
||||
@NonNull Date date, @NonNull String prefix) {
|
||||
pw.print(prefix);
|
||||
@@ -1141,11 +1357,20 @@ final class DiscreteRegistry {
|
||||
}
|
||||
|
||||
private static List<DiscreteOpEvent> filterEventsList(List<DiscreteOpEvent> list,
|
||||
long beginTimeMillis, long endTimeMillis, @AppOpsManager.OpFlags int flagsFilter) {
|
||||
long beginTimeMillis, long endTimeMillis, @AppOpsManager.OpFlags int flagsFilter,
|
||||
int currentUid, String currentPackageName, int currentOp, String currentAttrTag,
|
||||
ArrayMap<Integer, AttributionChain> attributionChains) {
|
||||
int n = list.size();
|
||||
List<DiscreteOpEvent> result = new ArrayList<>(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
DiscreteOpEvent event = list.get(i);
|
||||
AttributionChain chain = attributionChains.get(event.mAttributionChainId);
|
||||
// If we have an attribution chain, and this event isn't the beginning node, remove it
|
||||
if (chain != null && !chain.isStart(currentPackageName, currentUid, currentAttrTag,
|
||||
currentOp, event) && chain.isComplete()
|
||||
&& event.mAttributionChainId != ATTRIBUTION_CHAIN_ID_NONE) {
|
||||
continue;
|
||||
}
|
||||
if ((event.mOpFlag & flagsFilter) != 0
|
||||
&& event.mNoteTime + event.mNoteDuration > beginTimeMillis
|
||||
&& event.mNoteTime < endTimeMillis) {
|
||||
|
||||
@@ -370,7 +370,7 @@ final class HistoricalRegistry {
|
||||
@Nullable String attributionTag, @Nullable String[] opNames,
|
||||
@OpHistoryFlags int historyFlags, @HistoricalOpsRequestFilter int filter,
|
||||
long beginTimeMillis, long endTimeMillis, @OpFlags int flags,
|
||||
@NonNull RemoteCallback callback) {
|
||||
String[] attributionExemptedPackages, @NonNull RemoteCallback callback) {
|
||||
if (!isApiEnabled()) {
|
||||
callback.sendResult(new Bundle());
|
||||
return;
|
||||
@@ -396,7 +396,7 @@ final class HistoricalRegistry {
|
||||
if ((historyFlags & HISTORY_FLAG_DISCRETE) != 0) {
|
||||
mDiscreteRegistry.addFilteredDiscreteOpsToHistoricalOps(result, beginTimeMillis,
|
||||
endTimeMillis, filter, uid, packageName, opNames, attributionTag,
|
||||
flags);
|
||||
flags, new ArraySet<>(attributionExemptedPackages));
|
||||
}
|
||||
|
||||
final Bundle payload = new Bundle();
|
||||
@@ -407,7 +407,8 @@ final class HistoricalRegistry {
|
||||
void getHistoricalOps(int uid, @Nullable String packageName, @Nullable String attributionTag,
|
||||
@Nullable String[] opNames, @OpHistoryFlags int historyFlags,
|
||||
@HistoricalOpsRequestFilter int filter, long beginTimeMillis, long endTimeMillis,
|
||||
@OpFlags int flags, @NonNull RemoteCallback callback) {
|
||||
@OpFlags int flags, @Nullable String[] attributionExemptPkgs,
|
||||
@NonNull RemoteCallback callback) {
|
||||
if (!isApiEnabled()) {
|
||||
callback.sendResult(new Bundle());
|
||||
return;
|
||||
@@ -429,7 +430,8 @@ final class HistoricalRegistry {
|
||||
|
||||
if ((historyFlags & HISTORY_FLAG_DISCRETE) != 0) {
|
||||
mDiscreteRegistry.addFilteredDiscreteOpsToHistoricalOps(result, beginTimeMillis,
|
||||
endTimeMillis, filter, uid, packageName, opNames, attributionTag, flags);
|
||||
endTimeMillis, filter, uid, packageName, opNames, attributionTag, flags,
|
||||
new ArraySet<>(attributionExemptPkgs));
|
||||
}
|
||||
|
||||
if ((historyFlags & HISTORY_FLAG_AGGREGATE) != 0) {
|
||||
|
||||
@@ -5720,10 +5720,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
boolean fromDatasource, int attributedOp) {
|
||||
// Now let's check the identity chain...
|
||||
final int op = AppOpsManager.permissionToOpCode(permission);
|
||||
final int attributionChainId = (startDataDelivery)
|
||||
? sAttributionChainIds.incrementAndGet()
|
||||
: AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
|
||||
|
||||
final int attributionChainId =
|
||||
getAttributionChainId(startDataDelivery, attributionSource);
|
||||
AttributionSource current = attributionSource;
|
||||
AttributionSource next = null;
|
||||
|
||||
@@ -5879,9 +5877,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
return PermissionChecker.PERMISSION_HARD_DENIED;
|
||||
}
|
||||
|
||||
final int attributionChainId = (startDataDelivery)
|
||||
? sAttributionChainIds.incrementAndGet()
|
||||
: AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
|
||||
final int attributionChainId =
|
||||
getAttributionChainId(startDataDelivery, attributionSource);
|
||||
|
||||
AttributionSource current = attributionSource;
|
||||
AttributionSource next = null;
|
||||
@@ -6064,6 +6061,21 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private static int getAttributionChainId(boolean startDataDelivery,
|
||||
AttributionSource source) {
|
||||
if (source == null || source.getNext() == null || !startDataDelivery) {
|
||||
return AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
|
||||
}
|
||||
int attributionChainId = sAttributionChainIds.incrementAndGet();
|
||||
|
||||
// handle overflow
|
||||
if (attributionChainId < 0) {
|
||||
attributionChainId = 0;
|
||||
sAttributionChainIds.set(0);
|
||||
}
|
||||
return attributionChainId;
|
||||
}
|
||||
|
||||
private static @Nullable String resolvePackageName(@NonNull Context context,
|
||||
@NonNull AttributionSource attributionSource) {
|
||||
if (attributionSource.getPackageName() != null) {
|
||||
|
||||
Reference in New Issue
Block a user