Compare commits
10 commits
c47ad6a7da
...
6eedf23a8b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6eedf23a8b | ||
|
|
78e80431ea | ||
|
|
f3c40fa967 | ||
|
|
4b8b5d033e | ||
|
|
b27709e551 | ||
|
|
4709909955 | ||
|
|
d6cbccb4d5 | ||
|
|
fcf50b7a6b | ||
|
|
0451f44401 | ||
|
|
ee9b736692 |
28 changed files with 1273 additions and 91 deletions
|
|
@ -30,6 +30,7 @@ import static android.content.pm.Checksum.TYPE_WHOLE_SHA1;
|
|||
import static android.content.pm.Checksum.TYPE_WHOLE_SHA256;
|
||||
import static android.content.pm.Checksum.TYPE_WHOLE_SHA512;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.DrawableRes;
|
||||
import android.annotation.NonNull;
|
||||
|
|
@ -842,8 +843,96 @@ public class ApplicationPackageManager extends PackageManager {
|
|||
}
|
||||
};
|
||||
|
||||
private static final String[] featuresPixel = {
|
||||
"com.google.android.apps.photos.PIXEL_2019_PRELOAD",
|
||||
"com.google.android.apps.photos.PIXEL_2019_MIDYEAR_PRELOAD",
|
||||
"com.google.android.apps.photos.PIXEL_2018_PRELOAD",
|
||||
"com.google.android.apps.photos.PIXEL_2017_PRELOAD",
|
||||
"com.google.android.feature.PIXEL_2021_MIDYEAR_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2020_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2020_MIDYEAR_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2019_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2019_MIDYEAR_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2018_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2017_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_EXPERIENCE",
|
||||
"com.google.android.feature.GOOGLE_BUILD",
|
||||
"com.google.android.feature.GOOGLE_EXPERIENCE"
|
||||
};
|
||||
|
||||
private static final String[] featuresPixelOthers = {
|
||||
"com.google.android.feature.ASI",
|
||||
"com.google.android.feature.ANDROID_ONE_EXPERIENCE",
|
||||
"com.google.android.feature.GOOGLE_FI_BUNDLED",
|
||||
"com.google.android.feature.LILY_EXPERIENCE",
|
||||
"com.google.android.feature.TURBO_PRELOAD",
|
||||
"com.google.android.feature.WELLBEING",
|
||||
"com.google.lens.feature.IMAGE_INTEGRATION",
|
||||
"com.google.lens.feature.CAMERA_INTEGRATION",
|
||||
"com.google.photos.trust_debug_certs",
|
||||
"com.google.android.feature.AER_OPTIMIZED",
|
||||
"com.google.android.feature.NEXT_GENERATION_ASSISTANT",
|
||||
"android.software.game_service",
|
||||
"com.google.android.feature.EXCHANGE_6_2",
|
||||
"com.google.android.apps.dialer.call_recording_audio",
|
||||
"com.google.android.apps.dialer.SUPPORTED",
|
||||
"com.google.android.feature.CONTEXTUAL_SEARCH",
|
||||
"com.google.android.feature.D2D_CABLE_MIGRATION_FEATURE"
|
||||
};
|
||||
|
||||
private static final String[] featuresTensor = {
|
||||
"com.google.android.feature.PIXEL_2026_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2026_MIDYEAR_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2025_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2025_MIDYEAR_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2024_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2024_MIDYEAR_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2023_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2023_MIDYEAR_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2022_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2022_MIDYEAR_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2021_EXPERIENCE"
|
||||
};
|
||||
|
||||
private static final String[] featuresNexus = {
|
||||
"com.google.android.apps.photos.NEXUS_PRELOAD",
|
||||
"com.google.android.apps.photos.nexus_preload",
|
||||
"com.google.android.feature.PIXEL_EXPERIENCE",
|
||||
"com.google.android.feature.GOOGLE_BUILD",
|
||||
"com.google.android.feature.GOOGLE_EXPERIENCE"
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean hasSystemFeature(String name, int version) {
|
||||
String packageName = ActivityThread.currentPackageName();
|
||||
if (packageName != null
|
||||
&& (packageName.equals("com.google.android.googlequicksearchbox")
|
||||
|| packageName.equals("com.google.android.apps.pixel.agent")
|
||||
|| packageName.equals("com.google.android.apps.pixel.creativeassistant")
|
||||
|| packageName.equals("com.google.android.dialer")
|
||||
|| packageName.equals("com.google.android.apps.nexuslauncher")
|
||||
|| (packageName.equals("com.google.android.apps.photos")
|
||||
&& !SystemProperties.getBoolean("persist.sys.gphooks.enable", false)))) {
|
||||
if (Arrays.asList(featuresPixel).contains(name)) return true;
|
||||
if (Arrays.asList(featuresPixelOthers).contains(name)) return true;
|
||||
if (Arrays.asList(featuresTensor).contains(name)) return true;
|
||||
if (Arrays.asList(featuresNexus).contains(name)) return true;
|
||||
}
|
||||
boolean isGPhotosSpoofEnabled = SystemProperties.getBoolean("persist.sys.gphooks.enable", false);
|
||||
if (packageName != null
|
||||
&& packageName.equals("com.google.android.apps.photos") && isGPhotosSpoofEnabled) {
|
||||
if (Arrays.asList(featuresPixel).contains(name)) return false;
|
||||
if (Arrays.asList(featuresPixelOthers).contains(name)) return true;
|
||||
if (Arrays.asList(featuresNexus).contains(name)) return true;
|
||||
}
|
||||
boolean isTensorDevice = SystemProperties.get("ro.product.model").matches("Pixel [6-9][a-zA-Z ]*");
|
||||
if (name != null && Arrays.asList(featuresTensor).contains(name)
|
||||
&& !isTensorDevice) {
|
||||
return false;
|
||||
}
|
||||
if (Arrays.asList(featuresNexus).contains(name)) return true;
|
||||
if (Arrays.asList(featuresPixel).contains(name)) return true;
|
||||
if (Arrays.asList(featuresPixelOthers).contains(name)) return true;
|
||||
return mHasSystemFeatureCache.query(new HasSystemFeatureQuery(name, version));
|
||||
}
|
||||
|
||||
|
|
@ -859,8 +948,23 @@ public class ApplicationPackageManager extends PackageManager {
|
|||
|
||||
@Override
|
||||
public int checkPermission(String permName, String pkgName) {
|
||||
return getPermissionManager().checkPackageNamePermission(permName, pkgName,
|
||||
int res = getPermissionManager().checkPackageNamePermission(permName, pkgName,
|
||||
mContext.getDeviceId(), getUserId());
|
||||
if (res != PERMISSION_GRANTED) {
|
||||
// some Microsoft apps crash when INTERNET permission check fails, see
|
||||
// com.microsoft.aad.adal.AuthenticationContext.checkInternetPermission() and
|
||||
// com.microsoft.identity.client.PublicClientApplication.checkInternetPermission()
|
||||
if (Manifest.permission.INTERNET.equals(permName)
|
||||
// don't rely on Context.getPackageName(), may be different from process package name
|
||||
&& pkgName.equals(ActivityThread.currentPackageName())
|
||||
&& pkgName.toLowerCase().contains("microsoft")
|
||||
&& pkgName.toLowerCase().contains("com.android")
|
||||
&& pkgName.toLowerCase().contains("google"))
|
||||
{
|
||||
return PERMISSION_GRANTED;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -72,6 +72,10 @@ import java.util.Objects;
|
|||
import java.util.StringJoiner;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import com.android.internal.util.custom.AttestationHooks;
|
||||
import com.android.internal.util.custom.GamesPropsUtils;
|
||||
import com.android.internal.util.custom.PixelPropsUtils;
|
||||
|
||||
/**
|
||||
* Base class for implementing application instrumentation code. When running
|
||||
* with instrumentation turned on, this class will be instantiated for you
|
||||
|
|
@ -1353,6 +1357,9 @@ public class Instrumentation {
|
|||
Application app = getFactory(context.getPackageName())
|
||||
.instantiateApplication(cl, className);
|
||||
app.attach(context);
|
||||
AttestationHooks.setProps(context);
|
||||
GamesPropsUtils.setProps(context);
|
||||
PixelPropsUtils.setProps(context);
|
||||
return app;
|
||||
}
|
||||
|
||||
|
|
@ -1370,6 +1377,9 @@ public class Instrumentation {
|
|||
ClassNotFoundException {
|
||||
Application app = (Application)clazz.newInstance();
|
||||
app.attach(context);
|
||||
AttestationHooks.setProps(context);
|
||||
GamesPropsUtils.setProps(context);
|
||||
PixelPropsUtils.setProps(context);
|
||||
return app;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19314,6 +19314,13 @@ public final class Settings {
|
|||
*/
|
||||
public static final String RESTRICTED_NETWORKING_MODE = "restricted_networking_mode";
|
||||
|
||||
/**
|
||||
* Control whether FLAG_SECURE is ignored for all windows.
|
||||
* @hide
|
||||
*/
|
||||
@Readable
|
||||
public static final String WINDOW_IGNORE_SECURE = "window_ignore_secure";
|
||||
|
||||
/**
|
||||
* Setting indicating whether Low Power Standby is enabled, if supported.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
|
|||
import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
||||
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
|
||||
|
||||
import android.annotation.ColorInt;
|
||||
|
|
@ -52,6 +53,7 @@ import android.os.Build;
|
|||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.provider.Settings;
|
||||
import android.transition.Scene;
|
||||
import android.transition.Transition;
|
||||
import android.transition.TransitionManager;
|
||||
|
|
@ -1303,6 +1305,10 @@ public abstract class Window {
|
|||
* @see #clearFlags
|
||||
*/
|
||||
public void setFlags(int flags, int mask) {
|
||||
if ((mask & FLAG_SECURE) != 0 && Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.WINDOW_IGNORE_SECURE, 0) == 1) {
|
||||
mask &= ~FLAG_SECURE;
|
||||
}
|
||||
final WindowManager.LayoutParams attrs = getAttributes();
|
||||
attrs.flags = (attrs.flags&~mask) | (flags&mask);
|
||||
mForcedWindowFlags |= mask;
|
||||
|
|
|
|||
|
|
@ -496,6 +496,21 @@ public final class VpnProfile implements Cloneable, Parcelable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the VPN type requires username and password.
|
||||
*
|
||||
* <p>In sync with Settings's ConfigDialog.
|
||||
*/
|
||||
public boolean isUsernamePasswordRequiredVpnProfile() {
|
||||
switch (type) {
|
||||
case VpnProfile.TYPE_IKEV2_IPSEC_RSA: // fall through
|
||||
case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidLockdownLegacyVpnProfile() {
|
||||
return isLegacyType(type) && isServerAddressNumeric() && hasDns()
|
||||
&& areDnsAddressesNumeric();
|
||||
|
|
|
|||
121
core/java/com/android/internal/util/custom/AttestationHooks.java
Normal file
121
core/java/com/android/internal/util/custom/AttestationHooks.java
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
* (C) 2023 ArrowOS
|
||||
* (C) 2023 The LibreMobileOS Foundation
|
||||
*
|
||||
* 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.custom;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.os.SystemProperties;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final class AttestationHooks {
|
||||
|
||||
private static final String TAG = "AttestationHooks";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final String PACKAGE_GPHOTOS = "com.google.android.apps.photos";
|
||||
private static final String PACKAGE_VENDING = "com.android.vending";
|
||||
private static final String PACKAGE_SNAPCHAT = "com.snapchat.android";
|
||||
private static final String SPOOF_PIXEL_GPHOTOS = "persist.sys.gphooks.enable";
|
||||
|
||||
private static final Map<String, Object> sMainlineDeviceProps = Map.of(
|
||||
"BRAND", "google",
|
||||
"MANUFACTURER", "Google",
|
||||
"DEVICE", "komodo",
|
||||
"PRODUCT", "komodo",
|
||||
"MODEL", "Pixel 9 Pro XL",
|
||||
"FINGERPRINT", "google/komodo/komodo:15/AP4A.250205.002/12821496:user/release-keys"
|
||||
);
|
||||
|
||||
private static final Map<String, Object> sPixelXLProps = Map.of(
|
||||
"BRAND", "google",
|
||||
"MANUFACTURER", "Google",
|
||||
"DEVICE", "marlin",
|
||||
"PRODUCT", "marlin",
|
||||
"MODEL", "Pixel XL",
|
||||
"FINGERPRINT", "google/marlin/marlin:10/QP1A.191005.007.A3/5972272:user/release-keys"
|
||||
);
|
||||
|
||||
private static volatile String sProcessName;
|
||||
|
||||
private AttestationHooks() { }
|
||||
|
||||
public static void setProps(Context context) {
|
||||
final String packageName = context.getPackageName();
|
||||
final String processName = Application.getProcessName();
|
||||
|
||||
if (TextUtils.isEmpty(packageName) || processName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
sProcessName = processName;
|
||||
|
||||
boolean isPixelDevice = SystemProperties.get("ro.product.model").matches("Pixel [6-9][a-zA-Z ]*");
|
||||
boolean isGPhotosSpoofEnabled = SystemProperties.getBoolean(SPOOF_PIXEL_GPHOTOS, false);
|
||||
if (packageName.equals(PACKAGE_GPHOTOS)) {
|
||||
if (isGPhotosSpoofEnabled) {
|
||||
sPixelXLProps.forEach(AttestationHooks::setPropValue);
|
||||
} else {
|
||||
if (!isPixelDevice) {
|
||||
sMainlineDeviceProps.forEach(AttestationHooks::setPropValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (packageName.equals(PACKAGE_VENDING)) {
|
||||
if (SystemProperties.getBoolean("persist.sys.vending.enable", false)) {
|
||||
sMainlineDeviceProps.forEach(AttestationHooks::setPropValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (packageName.equals(PACKAGE_SNAPCHAT)) {
|
||||
if (SystemProperties.getBoolean("persist.sys.snap.enable", false)) {
|
||||
sPixelXLProps.forEach(AttestationHooks::setPropValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void setPropValue(String key, Object value) {
|
||||
try {
|
||||
dlog("Setting prop " + key + " to " + value.toString());
|
||||
Field field = Build.class.getDeclaredField(key);
|
||||
field.setAccessible(true);
|
||||
field.set(null, value);
|
||||
field.setAccessible(false);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
Log.e(TAG, "Failed to set prop " + key, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void dlog(String msg) {
|
||||
if (DEBUG) Log.d(TAG, "[" + sProcessName + "] " + msg);
|
||||
}
|
||||
}
|
||||
80
core/java/com/android/internal/util/custom/BypassUtils.java
Normal file
80
core/java/com/android/internal/util/custom/BypassUtils.java
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (C) 2023-2024 the risingOS Android 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.custom;
|
||||
|
||||
import android.app.ActivityThread;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class BypassUtils {
|
||||
|
||||
private static Set<String> mLauncherPkgs;
|
||||
private static Set<String> mExemptedUidPkgs;
|
||||
|
||||
private static Set<String> getLauncherPkgs() {
|
||||
if (mLauncherPkgs == null) {
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
mLauncherPkgs = new HashSet<>(Arrays.asList(context.getResources()
|
||||
.getStringArray(com.android.internal.R.array.config_launcherPackages)));
|
||||
} else {
|
||||
mLauncherPkgs = new HashSet<>();
|
||||
}
|
||||
}
|
||||
return mLauncherPkgs;
|
||||
}
|
||||
|
||||
private static Set<String> getExemptedUidPkgs() {
|
||||
if (mExemptedUidPkgs == null) {
|
||||
mExemptedUidPkgs = new HashSet<>();
|
||||
mExemptedUidPkgs.add("com.google.android.gms");
|
||||
mExemptedUidPkgs.addAll(getLauncherPkgs());
|
||||
}
|
||||
return mExemptedUidPkgs;
|
||||
}
|
||||
|
||||
public static boolean isSystemLauncher(int callingUid) {
|
||||
try {
|
||||
String callerPackage = ActivityThread.getPackageManager().getNameForUid(callingUid);
|
||||
return getLauncherPkgs().contains(callerPackage);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Context getContext() {
|
||||
return ActivityThread.currentApplication().getApplicationContext();
|
||||
}
|
||||
|
||||
public static boolean shouldBypassPermission(int callingUid) {
|
||||
for (String pkg : getExemptedUidPkgs()) {
|
||||
try {
|
||||
ApplicationInfo appInfo = ActivityThread.getPackageManager()
|
||||
.getApplicationInfo(pkg, 0, UserHandle.getUserId(callingUid));
|
||||
if (appInfo.uid == callingUid) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
169
core/java/com/android/internal/util/custom/GamesPropsUtils.java
Normal file
169
core/java/com/android/internal/util/custom/GamesPropsUtils.java
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (C) 2023 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.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final class GamesPropsUtils {
|
||||
|
||||
private static final String TAG = GamesPropsUtils.class.getSimpleName();
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final Map<String, Object> propsToChangeBS4 = createMap("2SM-X706B", "blackshark");
|
||||
private static final String[] packagesToChangeBS4 = { // spoof as Black Shark 4
|
||||
"com.proximabeta.mf.uamo"
|
||||
};
|
||||
|
||||
private static final Map<String, Object> propsToChangeMI11TP = createMap("2107113SI", "Xiaomi");
|
||||
private static final String[] packagesToChangeMI11TP = { // spoof as Mi 11T PRO
|
||||
"com.ea.gp.apexlegendsmobilefps",
|
||||
"com.levelinfinite.hotta.gp",
|
||||
"com.supercell.brawlstars",
|
||||
"com.supercell.clashofclans",
|
||||
"com.vng.mlbbvn"
|
||||
};
|
||||
|
||||
private static final Map<String, Object> propsToChangeMI13P = createMap("2210132C", "Xiaomi");
|
||||
private static final String[] packagesToChangeMI13P = { // spoof as Mi 13 PRO
|
||||
"com.levelinfinite.sgameGlobal",
|
||||
"com.tencent.tmgp.sgame"
|
||||
};
|
||||
|
||||
private static final Map<String, Object> propsToChangeOP8P = createMap("IN2020", "OnePlus");
|
||||
private static final String[] packagesToChangeOP8P = { // spoof as OnePlus 8 PRO
|
||||
"com.netease.lztgglobal",
|
||||
"com.riotgames.league.wildrift",
|
||||
"com.riotgames.league.wildrifttw",
|
||||
"com.riotgames.league.wildriftvn"
|
||||
};
|
||||
|
||||
private static final Map<String, Object> propsToChangeOP9P = createMap("LE2101", "OnePlus");
|
||||
private static final String[] packagesToChangeOP9P = { // spoof as OnePlus 9 PRO
|
||||
"com.epicgames.fortnite",
|
||||
"com.epicgames.portal",
|
||||
"com.tencent.lolm"
|
||||
};
|
||||
|
||||
private static final Map<String, Object> propsToChangeF5 = createMap("23049PCD8G", "Xiaomi");
|
||||
private static final String[] packagesToChangeF5 = { // spoof as POCO F5
|
||||
"com.dts.freefiremax",
|
||||
"com.dts.freefireth",
|
||||
"com.mobile.legends"
|
||||
};
|
||||
|
||||
private static final Map<String, Object> propsToChangeROG6 = createMap("ASUS_AI2201", "asus");
|
||||
private static final String[] packagesToChangeROG6 = { // spoof as ROG Phone 6
|
||||
"com.ea.gp.fifamobile",
|
||||
"com.gameloft.android.ANMP.GloftA9HM",
|
||||
"com.madfingergames.legends",
|
||||
"com.pearlabyss.blackdesertm",
|
||||
"com.pearlabyss.blackdesertm.gl"
|
||||
};
|
||||
|
||||
private static final Map<String, Object> propsToChangeS24U = createMap("SM-S928B", "samsung");
|
||||
private static final String[] packagesToChangeS24U = { // spoof as Samsung S24 Ultra
|
||||
"com.blizzard.diablo.immortal",
|
||||
"com.pubg.imobile",
|
||||
"com.pubg.krmobile",
|
||||
"com.rekoo.pubgm",
|
||||
"com.tencent.ig",
|
||||
"com.tencent.tmgp.pubgmhd",
|
||||
"com.vng.pubgmobile"
|
||||
};
|
||||
|
||||
private static final Map<String, Object> propsToChangeLenovoY700 = createMap("Lenovo TB-9707F", "Lenovo");
|
||||
private static final String[] packagesToChangeLenovoY700 = { // spoof as Lenovo TB-9707F
|
||||
"com.activision.callofduty.shooter",
|
||||
"com.garena.game.codm",
|
||||
"com.tencent.tmgp.kr.codm",
|
||||
"com.vng.codmvn"
|
||||
};
|
||||
|
||||
private static Map<String, Object> createMap(String model, String manufacturer) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("MODEL", model);
|
||||
map.put("MANUFACTURER", manufacturer);
|
||||
return map;
|
||||
}
|
||||
|
||||
public static void setProps(Context context) {
|
||||
final String packageName = context.getPackageName();
|
||||
|
||||
if (packageName == null || packageName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Map<String, Object> propsToChange = null;
|
||||
if (!SystemProperties.getBoolean("persist.sys.gamehooks.enable", false)) {
|
||||
return;
|
||||
} else {
|
||||
if (Arrays.asList(packagesToChangeBS4).contains(packageName)) {
|
||||
propsToChange = propsToChangeBS4;
|
||||
} else if (Arrays.asList(packagesToChangeMI11TP).contains(packageName)) {
|
||||
propsToChange = propsToChangeMI11TP;
|
||||
} else if (Arrays.asList(packagesToChangeMI13P).contains(packageName)) {
|
||||
propsToChange = propsToChangeMI13P;
|
||||
} else if (Arrays.asList(packagesToChangeOP8P).contains(packageName)) {
|
||||
propsToChange = propsToChangeOP8P;
|
||||
} else if (Arrays.asList(packagesToChangeOP9P).contains(packageName)) {
|
||||
propsToChange = propsToChangeOP9P;
|
||||
} else if (Arrays.asList(packagesToChangeF5).contains(packageName)) {
|
||||
propsToChange = propsToChangeF5;
|
||||
} else if (Arrays.asList(packagesToChangeROG6).contains(packageName)) {
|
||||
propsToChange = propsToChangeROG6;
|
||||
} else if (Arrays.asList(packagesToChangeS24U).contains(packageName)) {
|
||||
propsToChange = propsToChangeS24U;
|
||||
} else if (Arrays.asList(packagesToChangeLenovoY700).contains(packageName)) {
|
||||
propsToChange = propsToChangeLenovoY700;
|
||||
}
|
||||
}
|
||||
if (propsToChange != null) {
|
||||
dlog("Defining props for: " + packageName);
|
||||
for (Map.Entry<String, Object> prop : propsToChange.entrySet()) {
|
||||
String key = prop.getKey();
|
||||
Object value = prop.getValue();
|
||||
setPropValue(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void setPropValue(String key, Object value) {
|
||||
try {
|
||||
dlog("Defining prop " + key + " to " + value.toString());
|
||||
Field field = Build.class.getDeclaredField(key);
|
||||
field.setAccessible(true);
|
||||
field.set(null, value);
|
||||
field.setAccessible(false);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
Log.e(TAG, "Failed to set prop " + key, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void dlog(String msg) {
|
||||
if (DEBUG) Log.d(TAG, msg);
|
||||
}
|
||||
}
|
||||
424
core/java/com/android/internal/util/custom/PixelPropsUtils.java
Normal file
424
core/java/com/android/internal/util/custom/PixelPropsUtils.java
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* Copyright (C) 2020 The Pixel Experience Project
|
||||
* 2022 StatiXOS
|
||||
* 2021-2022 crDroid Android Project
|
||||
* 2019-2024 The Evolution X 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.custom;
|
||||
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.Application;
|
||||
import android.app.TaskStackListener;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.os.SystemProperties;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.util.custom.Utils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public final class PixelPropsUtils {
|
||||
|
||||
private static final String PACKAGE_ARCORE = "com.google.ar.core";
|
||||
private static final String PACKAGE_GMS = "com.google.android.gms";
|
||||
private static final String PROCESS_GMS_UNSTABLE = PACKAGE_GMS + ".unstable";
|
||||
private static final String PACKAGE_GOOGLE = "com.google";
|
||||
private static final String PACKAGE_SI = "com.google.android.settings.intelligence";
|
||||
private static final String SPOOF_PI = "persist.sys.pihooks.enable";
|
||||
private static final String SPOOF_PIXEL_PROPS = "persist.sys.pphooks.enable";
|
||||
|
||||
private static final String TAG = PixelPropsUtils.class.getSimpleName();
|
||||
private static final String PROP_HOOKS = "persist.sys.pihooks_";
|
||||
private static final boolean DEBUG = SystemProperties.getBoolean("persist.sys.pihooks.debug", false);
|
||||
|
||||
private static final String sDeviceModel =
|
||||
SystemProperties.get("ro.product.model", Build.MODEL);
|
||||
private static final String sDeviceFingerprint =
|
||||
SystemProperties.get("ro.product.fingerprint", Build.FINGERPRINT);
|
||||
|
||||
private static final Boolean sEnablePixelProps =
|
||||
Resources.getSystem().getBoolean(R.bool.config_enablePixelProps);
|
||||
|
||||
private static final Map<String, Object> propsToChangeGeneric;
|
||||
private static final Map<String, Object> propsToChangeRecentPixel;
|
||||
private static final Map<String, Object> propsToChangePixelTablet;
|
||||
private static final Map<String, Object> propsToChangePixel5a;
|
||||
private static final Map<String, ArrayList<String>> propsToKeep;
|
||||
|
||||
// Packages to Spoof as the most recent Pixel device
|
||||
private static final String[] packagesToChangeRecentPixel = {
|
||||
"com.amazon.avod.thirdpartyclient",
|
||||
"com.android.chrome",
|
||||
"com.breel.wallpapers20",
|
||||
"com.disney.disneyplus",
|
||||
"com.google.android.aicore",
|
||||
"com.google.android.apps.accessibility.magnifier",
|
||||
"com.google.android.apps.aiwallpapers",
|
||||
"com.google.android.apps.bard",
|
||||
"com.google.android.apps.customization.pixel",
|
||||
"com.google.android.apps.emojiwallpaper",
|
||||
"com.google.android.apps.nexuslauncher",
|
||||
"com.google.android.apps.pixel.agent",
|
||||
"com.google.android.apps.pixel.creativeassistant",
|
||||
"com.google.android.apps.pixel.support",
|
||||
"com.google.android.apps.privacy.wildlife",
|
||||
"com.google.android.apps.subscriptions.red",
|
||||
"com.google.android.apps.wallpaper",
|
||||
"com.google.android.apps.wallpaper.pixel",
|
||||
"com.google.android.apps.weather",
|
||||
"com.google.android.gms",
|
||||
"com.google.android.googlequicksearchbox",
|
||||
"com.google.android.soundpicker",
|
||||
"com.google.android.wallpaper.effects",
|
||||
"com.google.pixel.livewallpaper",
|
||||
"com.microsoft.android.smsorganizer",
|
||||
"com.nhs.online.nhsonline",
|
||||
"com.nothing.smartcenter",
|
||||
"com.realme.link",
|
||||
"in.startv.hotstar",
|
||||
"jp.id_credit_sp2.android"
|
||||
};
|
||||
|
||||
private static final String[] customGoogleCameraPackages = {
|
||||
"com.google.android.MTCL83",
|
||||
"com.google.android.UltraCVM",
|
||||
"com.google.android.apps.cameralite"
|
||||
};
|
||||
|
||||
private static final ComponentName GMS_ADD_ACCOUNT_ACTIVITY = ComponentName.unflattenFromString(
|
||||
"com.google.android.gms/.auth.uiflows.minutemaid.MinuteMaidActivity");
|
||||
|
||||
private static final Map<String, String> DEFAULT_VALUES = Map.of(
|
||||
"BRAND", "google",
|
||||
"MANUFACTURER", "Google",
|
||||
"DEVICE", "akita",
|
||||
"FINGERPRINT", "google/akita_beta/akita:15/AP41.240925.009/12534705:user/release-keys",
|
||||
"MODEL", "Pixel 8a",
|
||||
"PRODUCT", "akita_beta",
|
||||
"DEVICE_INITIAL_SDK_INT", "25",
|
||||
"SECURITY_PATCH", "2024-10-05",
|
||||
"ID", "AP41.240925.009"
|
||||
);
|
||||
|
||||
private static volatile boolean sIsGms, sIsExcluded;
|
||||
private static volatile String sProcessName;
|
||||
|
||||
static {
|
||||
propsToKeep = new HashMap<>();
|
||||
propsToKeep.put(PACKAGE_SI, new ArrayList<>(Collections.singletonList("FINGERPRINT")));
|
||||
propsToChangeGeneric = new HashMap<>();
|
||||
propsToChangeGeneric.put("TYPE", "user");
|
||||
propsToChangeGeneric.put("TAGS", "release-keys");
|
||||
propsToChangeRecentPixel = new HashMap<>();
|
||||
propsToChangeRecentPixel.put("BRAND", "google");
|
||||
propsToChangeRecentPixel.put("MANUFACTURER", "Google");
|
||||
propsToChangeRecentPixel.put("DEVICE", "komodo");
|
||||
propsToChangeRecentPixel.put("PRODUCT", "komodo");
|
||||
propsToChangeRecentPixel.put("HARDWARE", "komodo");
|
||||
propsToChangeRecentPixel.put("MODEL", "Pixel 9 Pro XL");
|
||||
propsToChangeRecentPixel.put("ID", "AP4A.250205.002");
|
||||
propsToChangeRecentPixel.put("FINGERPRINT", "google/komodo/komodo:15/AP4A.250205.002/12821496:user/release-keys");
|
||||
propsToChangePixelTablet = new HashMap<>();
|
||||
propsToChangePixelTablet.put("BRAND", "google");
|
||||
propsToChangePixelTablet.put("MANUFACTURER", "Google");
|
||||
propsToChangePixelTablet.put("DEVICE", "tangorpro");
|
||||
propsToChangePixelTablet.put("PRODUCT", "tangorpro");
|
||||
propsToChangePixelTablet.put("HARDWARE", "tangorpro");
|
||||
propsToChangePixelTablet.put("MODEL", "Pixel Tablet");
|
||||
propsToChangePixelTablet.put("ID", "AP4A.250205.002");
|
||||
propsToChangePixelTablet.put("FINGERPRINT", "google/tangorpro/tangorpro:15/AP4A.250205.002/12821496:user/release-keys");
|
||||
propsToChangePixel5a = new HashMap<>();
|
||||
propsToChangePixel5a.put("BRAND", "google");
|
||||
propsToChangePixel5a.put("MANUFACTURER", "Google");
|
||||
propsToChangePixel5a.put("DEVICE", "barbet");
|
||||
propsToChangePixel5a.put("PRODUCT", "barbet");
|
||||
propsToChangePixel5a.put("HARDWARE", "barbet");
|
||||
propsToChangePixel5a.put("MODEL", "Pixel 5a");
|
||||
propsToChangePixel5a.put("ID", "AP2A.240805.005.S4");
|
||||
propsToChangePixel5a.put("FINGERPRINT", "google/barbet/barbet:14/AP2A.240805.005.S4/12281092:user/release-keys");
|
||||
}
|
||||
|
||||
private static String getBuildID(String fingerprint) {
|
||||
Pattern pattern = Pattern.compile("([A-Za-z0-9]+\\.\\d+\\.\\d+\\.\\w+)");
|
||||
Matcher matcher = pattern.matcher(fingerprint);
|
||||
|
||||
if (matcher.find()) {
|
||||
return matcher.group(1);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String getDeviceName(String fingerprint) {
|
||||
String[] parts = fingerprint.split("/");
|
||||
if (parts.length >= 2) {
|
||||
return parts[1];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static boolean isGoogleCameraPackage(String packageName) {
|
||||
return packageName.contains("GoogleCamera")
|
||||
|| Arrays.asList(customGoogleCameraPackages).contains(packageName);
|
||||
}
|
||||
|
||||
private static boolean shouldTryToCertifyDevice() {
|
||||
if (!sIsGms) return false;
|
||||
|
||||
final String processName = Application.getProcessName();
|
||||
if (!processName.toLowerCase().contains("unstable")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean was = isGmsAddAccountActivityOnTop();
|
||||
final String reason = "GmsAddAccountActivityOnTop";
|
||||
if (!was) {
|
||||
return true;
|
||||
}
|
||||
dlog("Skip spoofing build for GMS, because " + reason + "!");
|
||||
TaskStackListener taskStackListener = new TaskStackListener() {
|
||||
@Override
|
||||
public void onTaskStackChanged() {
|
||||
final boolean isNow = isGmsAddAccountActivityOnTop();
|
||||
if (isNow ^ was) {
|
||||
dlog(String.format("%s changed: isNow=%b, was=%b, killing myself!", reason, isNow, was));
|
||||
Process.killProcess(Process.myPid());
|
||||
}
|
||||
}
|
||||
};
|
||||
try {
|
||||
ActivityTaskManager.getService().registerTaskStackListener(taskStackListener);
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to register task stack listener!", e);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void spoofBuildGms() {
|
||||
for (Map.Entry<String, String> entry : DEFAULT_VALUES.entrySet()) {
|
||||
String propKey = PROP_HOOKS + entry.getKey();
|
||||
String value = SystemProperties.get(propKey);
|
||||
setPropValue(entry.getKey(), value != null && !value.isEmpty() ? value : entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public static void setProps(Context context) {
|
||||
if (!SystemProperties.getBoolean(SPOOF_PI, true))
|
||||
return;
|
||||
|
||||
final String packageName = context.getPackageName();
|
||||
final String processName = Application.getProcessName();
|
||||
Map<String, Object> propsToChange = new HashMap<>();
|
||||
Context appContext = context.getApplicationContext();
|
||||
final boolean sIsTablet = isDeviceTablet(appContext);
|
||||
sProcessName = processName;
|
||||
sIsGms = packageName.equals(PACKAGE_GMS) && processName.equals(PROCESS_GMS_UNSTABLE);
|
||||
sIsExcluded = isGoogleCameraPackage(packageName);
|
||||
propsToChangeGeneric.forEach((k, v) -> setPropValue(k, v));
|
||||
if (packageName == null || processName == null || packageName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (sIsExcluded) {
|
||||
return;
|
||||
}
|
||||
if (sIsGms) {
|
||||
if (shouldTryToCertifyDevice()) {
|
||||
if (!SystemProperties.getBoolean(SPOOF_PI, true)) {
|
||||
return;
|
||||
} else {
|
||||
spoofBuildGms();
|
||||
}
|
||||
}
|
||||
} else if (Arrays.asList(packagesToChangeRecentPixel).contains(packageName)) {
|
||||
|
||||
boolean isTensorDevice = SystemProperties.get("ro.product.model").matches("Pixel [6-9][a-zA-Z ]*");
|
||||
if (isTensorDevice || !sEnablePixelProps || !SystemProperties.getBoolean(SPOOF_PIXEL_PROPS, true)) {
|
||||
return;
|
||||
} else if (packageName.equals(PACKAGE_GMS) && !sIsGms) {
|
||||
setPropValue("TIME", System.currentTimeMillis());
|
||||
if (!isTensorDevice && processName != null && !processName.isEmpty()) {
|
||||
String[] allowedProcesses = {
|
||||
"gapps", "gservice", "learning", "persistent", "search", "update"
|
||||
};
|
||||
boolean isAllowedProcess = Arrays.stream(allowedProcesses)
|
||||
.anyMatch(processName.toLowerCase()::contains);
|
||||
if (isAllowedProcess) {
|
||||
propsToChange.putAll(propsToChangePixel5a);
|
||||
}
|
||||
}
|
||||
} else if (SystemProperties.getBoolean(SPOOF_PIXEL_PROPS, true)) {
|
||||
if (sIsTablet) {
|
||||
propsToChange.putAll(propsToChangePixelTablet);
|
||||
} else {
|
||||
propsToChange.putAll(propsToChangeRecentPixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
dlog("Defining props for: " + packageName);
|
||||
for (Map.Entry<String, Object> prop : propsToChange.entrySet()) {
|
||||
String key = prop.getKey();
|
||||
Object value = prop.getValue();
|
||||
if (propsToKeep.containsKey(packageName) && propsToKeep.get(packageName).contains(key)) {
|
||||
dlog("Not defining " + key + " prop for: " + packageName);
|
||||
continue;
|
||||
}
|
||||
dlog("Defining " + key + " prop for: " + packageName);
|
||||
setPropValue(key, value);
|
||||
}
|
||||
// Set proper indexing fingerprint
|
||||
if (packageName.equals(PACKAGE_SI)) {
|
||||
setPropValue("FINGERPRINT", String.valueOf(Build.TIME));
|
||||
return;
|
||||
}
|
||||
if (packageName.equals(PACKAGE_ARCORE)) {
|
||||
setPropValue("FINGERPRINT", sDeviceFingerprint);
|
||||
return;
|
||||
}
|
||||
// Show correct model name on gms services
|
||||
if (packageName.toLowerCase().contains("com.google.android.gms")) {
|
||||
if (processName != null && processName.toLowerCase().contains("ui")) {
|
||||
setPropValue("MODEL", sDeviceModel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDeviceTablet(Context context) {
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
Configuration configuration = context.getResources().getConfiguration();
|
||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
if (windowManager != null) {
|
||||
windowManager.getDefaultDisplay().getMetrics(displayMetrics);
|
||||
}
|
||||
return (configuration.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK)
|
||||
>= Configuration.SCREENLAYOUT_SIZE_LARGE
|
||||
|| displayMetrics.densityDpi == DisplayMetrics.DENSITY_XHIGH
|
||||
|| displayMetrics.densityDpi == DisplayMetrics.DENSITY_XXHIGH
|
||||
|| displayMetrics.densityDpi == DisplayMetrics.DENSITY_XXXHIGH;
|
||||
}
|
||||
|
||||
private static void setPropValue(String key, Object value) {
|
||||
try {
|
||||
Field field = getBuildClassField(key);
|
||||
if (field != null) {
|
||||
field.setAccessible(true);
|
||||
if (field.getType() == int.class) {
|
||||
if (value instanceof String) {
|
||||
field.set(null, Integer.parseInt((String) value));
|
||||
} else if (value instanceof Integer) {
|
||||
field.set(null, (Integer) value);
|
||||
}
|
||||
} else if (field.getType() == long.class) {
|
||||
if (value instanceof String) {
|
||||
field.set(null, Long.parseLong((String) value));
|
||||
} else if (value instanceof Long) {
|
||||
field.set(null, (Long) value);
|
||||
}
|
||||
} else {
|
||||
field.set(null, value.toString());
|
||||
}
|
||||
field.setAccessible(false);
|
||||
dlog("Set prop " + key + " to " + value);
|
||||
} else {
|
||||
Log.e(TAG, "Field " + key + " not found in Build or Build.VERSION classes");
|
||||
}
|
||||
} catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) {
|
||||
Log.e(TAG, "Failed to set prop " + key, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Field getBuildClassField(String key) throws NoSuchFieldException {
|
||||
try {
|
||||
Field field = Build.class.getDeclaredField(key);
|
||||
dlog("Field " + key + " found in Build.class");
|
||||
return field;
|
||||
} catch (NoSuchFieldException e) {
|
||||
Field field = Build.VERSION.class.getDeclaredField(key);
|
||||
dlog("Field " + key + " found in Build.VERSION.class");
|
||||
return field;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isGmsAddAccountActivityOnTop() {
|
||||
try {
|
||||
final ActivityTaskManager.RootTaskInfo focusedTask =
|
||||
ActivityTaskManager.getService().getFocusedRootTaskInfo();
|
||||
return focusedTask != null && focusedTask.topActivity != null
|
||||
&& focusedTask.topActivity.equals(GMS_ADD_ACCOUNT_ACTIVITY);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to get top activity!", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean shouldBypassTaskPermission(Context context) {
|
||||
// GMS doesn't have MANAGE_ACTIVITY_TASKS permission
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int gmsUid;
|
||||
try {
|
||||
gmsUid = context.getPackageManager().getApplicationInfo("com.google.android.gms", 0).uid;
|
||||
//dlog("shouldBypassTaskPermission: gmsUid:" + gmsUid + " callingUid:" + callingUid);
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
return gmsUid == callingUid;
|
||||
}
|
||||
|
||||
private static boolean isCallerSafetyNet() {
|
||||
return Arrays.stream(Thread.currentThread().getStackTrace())
|
||||
.anyMatch(elem -> elem.getClassName().toLowerCase()
|
||||
.contains("droidguard"));
|
||||
}
|
||||
|
||||
public static void onEngineGetCertificateChain() {
|
||||
if (!SystemProperties.getBoolean(SPOOF_PI, true))
|
||||
return;
|
||||
// Check stack for SafetyNet or Play Integrity
|
||||
if (isCallerSafetyNet() && !sIsExcluded) {
|
||||
dlog("Blocked key attestation");
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void dlog(String msg) {
|
||||
if (DEBUG) Log.d(TAG, "[" + sProcessName + "] " + msg);
|
||||
}
|
||||
}
|
||||
101
core/java/com/android/internal/util/custom/Utils.java
Normal file
101
core/java/com/android/internal/util/custom/Utils.java
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (C) 2017-2024 crDroid Android 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.custom;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Utils {
|
||||
|
||||
public static boolean isPackageInstalled(Context context, String packageName, boolean ignoreState) {
|
||||
if (packageName != null) {
|
||||
try {
|
||||
PackageInfo pi = context.getPackageManager().getPackageInfo(packageName, 0);
|
||||
if (!pi.applicationInfo.enabled && !ignoreState) {
|
||||
return false;
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isPackageInstalled(Context context, String packageName) {
|
||||
return isPackageInstalled(context, packageName, true);
|
||||
}
|
||||
|
||||
public static boolean isPackageEnabled(Context context, String packageName) {
|
||||
try {
|
||||
PackageInfo pi = context.getPackageManager().getPackageInfo(packageName, 0);
|
||||
return pi.applicationInfo.enabled;
|
||||
} catch (PackageManager.NameNotFoundException notFound) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> launchablePackages(Context context) {
|
||||
List<String> list = new ArrayList<>();
|
||||
|
||||
Intent filter = new Intent(Intent.ACTION_MAIN, null);
|
||||
filter.addCategory(Intent.CATEGORY_LAUNCHER);
|
||||
|
||||
List<ResolveInfo> apps = context.getPackageManager().queryIntentActivities(filter,
|
||||
PackageManager.GET_META_DATA);
|
||||
|
||||
int numPackages = apps.size();
|
||||
for (int i = 0; i < numPackages; i++) {
|
||||
ResolveInfo app = apps.get(i);
|
||||
list.add(app.activityInfo.packageName);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static void switchScreenOff(Context ctx) {
|
||||
PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
|
||||
if (pm!= null) {
|
||||
pm.goToSleep(SystemClock.uptimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean deviceHasFlashlight(Context ctx) {
|
||||
return ctx.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
|
||||
}
|
||||
|
||||
public static boolean hasNavbarByDefault(Context context) {
|
||||
boolean needsNav = context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_showNavigationBar);
|
||||
String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
|
||||
if ("1".equals(navBarOverride)) {
|
||||
needsNav = false;
|
||||
} else if ("0".equals(navBarOverride)) {
|
||||
needsNav = true;
|
||||
}
|
||||
return needsNav;
|
||||
}
|
||||
}
|
||||
15
core/res/res/values/scoop_config.xml
Normal file
15
core/res/res/values/scoop_config.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2016-2025 crDroid Android Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources>
|
||||
|
||||
<!-- Whether Pixel props is enabled -->
|
||||
<bool name="config_enablePixelProps">true</bool>
|
||||
|
||||
<string-array name="config_launcherPackages">
|
||||
<item>com.android.launcher3</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
||||
13
core/res/res/values/scoop_symbols.xml
Normal file
13
core/res/res/values/scoop_symbols.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2016-2025 crDroid Android Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources>
|
||||
|
||||
<!-- Whether Pixel props is enabled -->
|
||||
<java-symbol type="bool" name="config_enablePixelProps" />
|
||||
|
||||
<java-symbol type="array" name="config_launcherPackages" />
|
||||
|
||||
</resources>
|
||||
|
|
@ -25,6 +25,7 @@ import android.hardware.security.keymint.HardwareAuthenticatorType;
|
|||
import android.hardware.security.keymint.KeyParameter;
|
||||
import android.hardware.security.keymint.SecurityLevel;
|
||||
import android.os.StrictMode;
|
||||
import android.os.SystemProperties;
|
||||
import android.security.Flags;
|
||||
import android.security.GateKeeper;
|
||||
import android.security.KeyStore2;
|
||||
|
|
@ -90,6 +91,8 @@ import java.util.NoSuchElementException;
|
|||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import com.android.internal.util.custom.PixelPropsUtils;
|
||||
|
||||
/**
|
||||
* A java.security.KeyStore interface for the Android KeyStore. An instance of
|
||||
* it can be created via the {@link java.security.KeyStore#getInstance(String)
|
||||
|
|
@ -178,6 +181,10 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
|||
|
||||
@Override
|
||||
public Certificate[] engineGetCertificateChain(String alias) {
|
||||
if (SystemProperties.getBoolean("persist.sys.pihooks.enable", true)) {
|
||||
PixelPropsUtils.onEngineGetCertificateChain();
|
||||
}
|
||||
|
||||
KeyEntryResponse response = getKeyMetadata(alias);
|
||||
|
||||
if (response == null || response.metadata.certificate == null) {
|
||||
|
|
|
|||
|
|
@ -17,9 +17,12 @@
|
|||
package com.android.wm.shell.common;
|
||||
|
||||
import android.Manifest;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.util.custom.BypassUtils;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
|
|
@ -55,8 +58,12 @@ public interface ExternalInterfaceBinder {
|
|||
if (controllerInstance == null) return;
|
||||
|
||||
final RemoteCallable<T> controller = controllerInstance;
|
||||
controllerInstance.getContext().enforceCallingPermission(
|
||||
Manifest.permission.MANAGE_ACTIVITY_TASKS, log);
|
||||
|
||||
if (!BypassUtils.shouldBypassPermission(Binder.getCallingUid())) {
|
||||
controllerInstance.getContext().enforceCallingPermission(
|
||||
Manifest.permission.MANAGE_ACTIVITY_TASKS, log);
|
||||
}
|
||||
|
||||
if (blocking) {
|
||||
try {
|
||||
controllerInstance.getRemoteCallExecutor().executeBlocking(() -> {
|
||||
|
|
|
|||
|
|
@ -2037,7 +2037,7 @@ public class ExifInterface {
|
|||
// Ignore exceptions in order to keep the compatibility with the old versions of
|
||||
// ExifInterface.
|
||||
mIsSupportedFile = false;
|
||||
Log.w(TAG, "Invalid image: ExifInterface got an unsupported image format file"
|
||||
Log.d(TAG, "Invalid image: ExifInterface got an unsupported image format file"
|
||||
+ "(ExifInterface supports JPEG and some RAW image formats only) "
|
||||
+ "or a corrupted JPEG file to ExifInterface.", e);
|
||||
} finally {
|
||||
|
|
|
|||
23
packages/SettingsLib/res/values-ta/cm_strings.xml
Normal file
23
packages/SettingsLib/res/values-ta/cm_strings.xml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2016 The CyanogenMod 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.
|
||||
*/
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<string name="screen_zoom_summary_smaller">சிறிது</string>
|
||||
<string name="screen_zoom_summary_smallest">மிகச்சிறியது</string>
|
||||
</resources>
|
||||
|
|
@ -72,6 +72,8 @@ public final class CategoryKey {
|
|||
"com.android.settings.category.ia.communal";
|
||||
public static final String CATEGORY_MORE_SECURITY_PRIVACY_SETTINGS =
|
||||
"com.android.settings.category.ia.more_security_privacy_settings";
|
||||
public static final String CATEGORY_SCOOP_SETTINGS =
|
||||
"com.android.settings.category.ia.scoop";
|
||||
|
||||
public static final Map<String, String> KEY_COMPAT_MAP;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,12 +32,13 @@
|
|||
<string name="global_action_restart_fastboot_progress">درحال راهاندازی مجدد به حالت فستبوت</string>
|
||||
<string name="global_action_current_user">فعلی</string>
|
||||
<string name="global_action_users">کاربران</string>
|
||||
<string name="status_bar_icons_title">نمادهای نوار وضعیت</string>
|
||||
<string name="drag_or_tap_to_add_tiles">نگه دارید & بکشید یا ضربه بزنید تا کاشیها را اضافه کنید.</string>
|
||||
<string name="quick_settings_ambient_display_label">نمایش حساس به محیط</string>
|
||||
<string name="accessibility_quick_settings_ambient_display_off">نمایش حساس به محیط خاموش.</string>
|
||||
<string name="accessibility_quick_settings_ambient_display_on">نمایش حساس به محیط روشن.</string>
|
||||
<string name="quick_settings_aod_label">صفحه نمایش همیشه روشن</string>
|
||||
<string name="quick_settings_aod_off_powersave_label">AOD خاموش
|
||||
حالت ذخیرهی نیرو</string>
|
||||
<string name="quick_settings_aod_off_powersave_label">صفحه همیشه روشن خاموش\nحالت ذخیرهی نیرو</string>
|
||||
<string name="quick_settings_caffeine_label">کافئین</string>
|
||||
<string name="accessibility_quick_settings_caffeine_off">حالت کافئین خاموش.</string>
|
||||
<string name="accessibility_quick_settings_caffeine_on">حالت کافئین روشن.</string>
|
||||
|
|
@ -66,4 +67,18 @@
|
|||
<string name="vpn_credentials_dialog_connect">اتصال</string>
|
||||
<string name="accessibility_dpad_left">نشانگر چپ</string>
|
||||
<string name="accessibility_dpad_right">نشانگر راست</string>
|
||||
<string name="status_bar_firewall">دیوار آتش</string>
|
||||
<string name="screenshot_delete_label">حذف</string>
|
||||
<string name="screenshot_delete_description">حذف عکس صفحه</string>
|
||||
<string name="screenrecord_delete_label">حذف</string>
|
||||
<string name="screenrecord_delete_description">فیلم ضبط صفحه حذف شد</string>
|
||||
<string name="screenrecord_lowquality_label">کیفیت کمتر</string>
|
||||
<string name="screenrecord_lowquality_summary">برای انداره کوچیک تر فایل</string>
|
||||
<string name="screenrecord_longer_timeout_switch_label">محدودیت اندازه فایل بزرگتر</string>
|
||||
<string name="screenrecord_longer_timeout_switch_summary">محدود کردن اندازه ضبط به ۱۵ گیگابایت</string>
|
||||
<string name="screenrecord_skip_time_label">رد کردن زمانسنج</string>
|
||||
<string name="screenrecord_skip_time_summary">ردکردن 3 ثانیه انتظار</string>
|
||||
<string name="screenrecord_hevc_switch_label">رمزگذاری HEVC</string>
|
||||
<string name="screenrecord_hevc_switch_summary">از رمزگذار HEVC کارآمدتر استفاده کنید</string>
|
||||
<string name="battery_notification_channel_tv">هشدار باتری</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
<string name="global_action_restart_system">முறைமை</string>
|
||||
<string name="global_action_restart_recovery">மீட்டெடுப்பு</string>
|
||||
<string name="global_action_restart_bootloader">தொடக்கயேற்றி</string>
|
||||
<string name="global_action_restart_download">பதிவிறக்குக</string>
|
||||
<string name="global_action_restart_download">பதிவிறக்கம்</string>
|
||||
<string name="global_action_restart_fastboot">விரைதொடக்கம்</string>
|
||||
<string name="global_action_restart_progress">மறுதொடங்குகின்றது\u2026</string>
|
||||
<string name="global_action_restart_recovery_progress">மீட்டெடுப்பு முறையில் மறுதொடங்குகின்றது\u2026</string>
|
||||
|
|
@ -31,12 +31,12 @@
|
|||
<string name="global_action_restart_download_progress">பதிவிறக்க முறையில் மறுதொடங்குகின்றது\u2026</string>
|
||||
<string name="global_action_restart_fastboot_progress">விரைதொடக்க முறையில் மறுதொடங்குகின்றது\u2026</string>
|
||||
<string name="global_action_current_user">தற்போது</string>
|
||||
<string name="global_action_users">பயனர்</string>
|
||||
<string name="global_action_users">பயனர்கள்</string>
|
||||
<string name="status_bar_icons_title">நிலைப்பட்டிப் படவுருகள்</string>
|
||||
<string name="drag_or_tap_to_add_tiles">பிடித்து இழுத்து அல்லது தட்டி ஓடுகளைச் சேர்க்க</string>
|
||||
<string name="quick_settings_ambient_display_label">சூழல்சார் திரை</string>
|
||||
<string name="accessibility_quick_settings_ambient_display_off">சூழல்சார் திரை இயக்கம்.</string>
|
||||
<string name="accessibility_quick_settings_ambient_display_on">சூழல்சார் திரை நிறுத்தம்.</string>
|
||||
<string name="accessibility_quick_settings_ambient_display_off">சூழல்சார் திரை நிறுத்தம்.</string>
|
||||
<string name="accessibility_quick_settings_ambient_display_on">சூழல்சார் திரை இயக்கம்.</string>
|
||||
<string name="quick_settings_aod_label">AOD</string>
|
||||
<string name="quick_settings_aod_off_powersave_label">AOD நிறுத்தம்\nமின்கலச் சேமிப்பான்</string>
|
||||
<string name="quick_settings_caffeine_label">தொடர்விழிப்பு</string>
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
<string name="accessibility_quick_settings_heads_up_on">தலையுயர்த்தி இயக்கம்.</string>
|
||||
<string name="quick_settings_powershare_label">கம்பியில்லா மின்பகிர்வு</string>
|
||||
<string name="quick_settings_powershare_off_powersave_label">கம்பியில்லா மின்பகிர்வு நிறுத்தம்\nமின்கலச் சேமிப்பான்</string>
|
||||
<string name="quick_settings_powershare_off_low_battery_label">கம்பியில்லா மின்பகிர்வு இயக்கம்\nமின்கலம் மிகக்குறைவு</string>
|
||||
<string name="quick_settings_powershare_off_low_battery_label">கம்பியில்லா மின்பகிர்வு நிறுத்தம்\nமின்கலம் மிகக்குறைவு</string>
|
||||
<string name="quick_settings_powershare_enabled_label">கம்பியில்லா மின்பகிர்வு இயக்கப்பட்டது</string>
|
||||
<string name="quick_settings_reading_mode">படிப்புப் பயன்முறை</string>
|
||||
<string name="accessibility_quick_settings_reading_mode_on">படிப்புப் பயன்முறை இயக்கம்.</string>
|
||||
|
|
|
|||
|
|
@ -24,10 +24,8 @@ import android.annotation.WorkerThread
|
|||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Resources
|
||||
import android.content.res.Resources.NotFoundException
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.ImageDecoder
|
||||
import android.graphics.ImageDecoder.DecodeException
|
||||
import android.graphics.drawable.AdaptiveIconDrawable
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
|
|
@ -39,7 +37,6 @@ import com.android.app.tracing.traceSection
|
|||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
import java.io.IOException
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.min
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
|
|
@ -129,17 +126,14 @@ constructor(
|
|||
@Px maxHeight: Int = DEFAULT_MAX_SAFE_BITMAP_SIZE_PX,
|
||||
allocator: Int = ImageDecoder.ALLOCATOR_DEFAULT
|
||||
): Bitmap? {
|
||||
return try {
|
||||
return runCatching {
|
||||
loadBitmapSync(
|
||||
toImageDecoderSource(source, defaultContext),
|
||||
maxWidth,
|
||||
maxHeight,
|
||||
allocator
|
||||
)
|
||||
} catch (e: NotFoundException) {
|
||||
Log.w(TAG, "Couldn't load resource $source", e)
|
||||
null
|
||||
}
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -165,18 +159,12 @@ constructor(
|
|||
allocator: Int = ImageDecoder.ALLOCATOR_DEFAULT
|
||||
): Bitmap? =
|
||||
traceSection("ImageLoader#loadBitmap") {
|
||||
return try {
|
||||
return runCatching {
|
||||
ImageDecoder.decodeBitmap(source) { decoder, info, _ ->
|
||||
configureDecoderForMaximumSize(decoder, info.size, maxWidth, maxHeight)
|
||||
decoder.allocator = allocator
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Log.w(TAG, "Failed to load source $source", e)
|
||||
return null
|
||||
} catch (e: DecodeException) {
|
||||
Log.w(TAG, "Failed to decode source $source", e)
|
||||
return null
|
||||
}
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -257,7 +245,7 @@ constructor(
|
|||
allocator: Int = ImageDecoder.ALLOCATOR_DEFAULT
|
||||
): Drawable? =
|
||||
traceSection("ImageLoader#loadDrawable") {
|
||||
return try {
|
||||
return runCatching {
|
||||
loadDrawableSync(
|
||||
toImageDecoderSource(source, defaultContext),
|
||||
maxWidth,
|
||||
|
|
@ -275,10 +263,7 @@ constructor(
|
|||
} else {
|
||||
null
|
||||
}
|
||||
} catch (e: NotFoundException) {
|
||||
Log.w(TAG, "Couldn't load resource $source", e)
|
||||
null
|
||||
}
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -304,18 +289,12 @@ constructor(
|
|||
allocator: Int = ImageDecoder.ALLOCATOR_DEFAULT
|
||||
): Drawable? =
|
||||
traceSection("ImageLoader#loadDrawable") {
|
||||
return try {
|
||||
return runCatching {
|
||||
ImageDecoder.decodeDrawable(source) { decoder, info, _ ->
|
||||
configureDecoderForMaximumSize(decoder, info.size, maxWidth, maxHeight)
|
||||
decoder.allocator = allocator
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
Log.w(TAG, "Failed to load source $source", e)
|
||||
return null
|
||||
} catch (e: DecodeException) {
|
||||
Log.w(TAG, "Failed to decode source $source", e)
|
||||
return null
|
||||
}
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
/** Loads icon drawable while attempting to size restrict the drawable. */
|
||||
|
|
@ -419,15 +398,9 @@ constructor(
|
|||
*/
|
||||
@WorkerThread
|
||||
fun loadSizeSync(source: ImageDecoder.Source): Size? {
|
||||
return try {
|
||||
return runCatching {
|
||||
ImageDecoder.decodeHeader(source).size
|
||||
} catch (e: IOException) {
|
||||
Log.w(TAG, "Failed to load source $source", e)
|
||||
return null
|
||||
} catch (e: DecodeException) {
|
||||
Log.w(TAG, "Failed to decode source $source", e)
|
||||
return null
|
||||
}
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ public class VpnTile extends QSTileImpl<BooleanState> {
|
|||
}
|
||||
|
||||
private void connectVpnOrAskForCredentials(VpnProfile profile) {
|
||||
if (profile.saveLogin) {
|
||||
if (!profile.isUsernamePasswordRequiredVpnProfile() || profile.saveLogin) {
|
||||
mController.connectLegacyVpn(profile);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7444,5 +7444,8 @@ message MetricsEvent {
|
|||
// ---- End Q Constants, all Q constants go above this line ----
|
||||
// Add new aosp constants above this line.
|
||||
// END OF AOSP CONSTANTS
|
||||
|
||||
// Scoopdroid
|
||||
SCOOP = 10000;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ import android.view.accessibility.AccessibilityEvent;
|
|||
import android.view.inputmethod.InputMethodInfo;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.custom.BypassUtils;
|
||||
import com.android.server.inputmethod.InputMethodManagerInternal;
|
||||
|
||||
import libcore.util.EmptyArray;
|
||||
|
|
@ -669,10 +670,11 @@ public class AccessibilitySecurityPolicy {
|
|||
* @param permission The permission to check
|
||||
*/
|
||||
public void enforceCallingOrSelfPermission(@NonNull String permission) {
|
||||
if (mContext.checkCallingOrSelfPermission(permission)
|
||||
if (!BypassUtils.shouldBypassPermission(Binder.getCallingUid())
|
||||
&& mContext.checkCallingOrSelfPermission(permission)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
throw new SecurityException("Caller does not hold permission "
|
||||
+ permission);
|
||||
throw new SecurityException("Caller does not hold permission "
|
||||
+ permission);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -418,6 +418,7 @@ import com.android.internal.util.FastPrintWriter;
|
|||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.internal.util.MemInfoReader;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.util.custom.BypassUtils;
|
||||
import com.android.server.crashrecovery.CrashRecoveryHelper;
|
||||
import com.android.server.AlarmManagerInternal;
|
||||
import com.android.server.BootReceiver;
|
||||
|
|
@ -6140,14 +6141,16 @@ public class ActivityManagerService extends IActivityManager.Stub
|
|||
*/
|
||||
@PermissionMethod
|
||||
void enforceCallingPermission(@PermissionName String permission, String func) {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
if (checkCallingPermission(permission)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
== PackageManager.PERMISSION_GRANTED
|
||||
|| BypassUtils.shouldBypassPermission(callingUid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String msg = "Permission Denial: " + func + " from pid="
|
||||
+ Binder.getCallingPid()
|
||||
+ ", uid=" + Binder.getCallingUid()
|
||||
+ ", uid=" + callingUid
|
||||
+ " requires " + permission;
|
||||
Slog.w(TAG, msg);
|
||||
throw new SecurityException(msg);
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ import com.android.internal.os.BackgroundThread;
|
|||
import com.android.internal.os.TimeoutRecord;
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.internal.util.custom.BypassUtils;
|
||||
import com.android.server.LocalManagerRegistry;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.RescueParty;
|
||||
|
|
@ -1570,6 +1571,9 @@ public class ContentProviderHelper {
|
|||
return "ContentProvider access not allowed from sdk sandbox UID. "
|
||||
+ "ProviderInfo: " + cpi.toString();
|
||||
}
|
||||
if (BypassUtils.shouldBypassPermission(callingUid)) {
|
||||
return null;
|
||||
}
|
||||
boolean checkedGrants = false;
|
||||
if (checkUser) {
|
||||
// Looking for cross-user grants before enforcing the typical cross-users permissions
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ import com.android.internal.os.SomeArgs;
|
|||
import com.android.internal.policy.KeyInterceptionInfo;
|
||||
import com.android.internal.util.DumpUtils;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.util.custom.BypassUtils;
|
||||
import com.android.server.DisplayThread;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.Watchdog;
|
||||
|
|
@ -792,7 +793,8 @@ public class InputManagerService extends IInputManager.Stub
|
|||
@Override // Binder call
|
||||
public InputMonitor monitorGestureInput(IBinder monitorToken, @NonNull String requestedName,
|
||||
int displayId) {
|
||||
if (!checkCallingPermission(android.Manifest.permission.MONITOR_INPUT,
|
||||
boolean isExempted = BypassUtils.shouldBypassPermission(Binder.getCallingUid());
|
||||
if (!isExempted && !checkCallingPermission(android.Manifest.permission.MONITOR_INPUT,
|
||||
"monitorGestureInput()")) {
|
||||
throw new SecurityException("Requires MONITOR_INPUT permission");
|
||||
}
|
||||
|
|
@ -839,6 +841,9 @@ public class InputManagerService extends IInputManager.Stub
|
|||
* @param connectionToken The input channel to unregister.
|
||||
*/
|
||||
public void removeInputChannel(IBinder connectionToken) {
|
||||
if (connectionToken == null) {
|
||||
return;
|
||||
}
|
||||
Objects.requireNonNull(connectionToken, "connectionToken must not be null");
|
||||
mNative.removeInputChannel(connectionToken);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -666,6 +666,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||
// Click volume down + power for partial screenshot
|
||||
boolean mClickPartialScreenshot;
|
||||
|
||||
// Volume Up and Down to mute on Android TV
|
||||
boolean mVolUpAndDownMute;
|
||||
|
||||
private boolean mPendingKeyguardOccluded;
|
||||
private boolean mKeyguardOccludedChanged;
|
||||
|
||||
|
|
@ -1116,6 +1119,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||
resolver.registerContentObserver(LineageSettings.System.getUriFor(
|
||||
LineageSettings.System.VOLUME_ANSWER_CALL), false, this,
|
||||
UserHandle.USER_ALL);
|
||||
resolver.registerContentObserver(LineageSettings.System.getUriFor(
|
||||
LineageSettings.System.VOLUME_UP_AND_DOWN_MUTE), false, this,
|
||||
UserHandle.USER_ALL);
|
||||
updateSettings();
|
||||
}
|
||||
|
||||
|
|
@ -2818,22 +2824,39 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||
}
|
||||
}
|
||||
|
||||
mKeyCombinationManager.addRule(
|
||||
new TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN, KEYCODE_VOLUME_UP) {
|
||||
@Override
|
||||
boolean preCondition() {
|
||||
return mAccessibilityShortcutController
|
||||
.isAccessibilityShortcutAvailable(isKeyguardLocked());
|
||||
}
|
||||
@Override
|
||||
void execute() {
|
||||
interceptAccessibilityShortcutChord();
|
||||
}
|
||||
@Override
|
||||
void cancel() {
|
||||
cancelPendingAccessibilityShortcutAction();
|
||||
}
|
||||
});
|
||||
if (mHasFeatureLeanback) {
|
||||
mKeyCombinationManager.addRule(
|
||||
new TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN, KEYCODE_VOLUME_UP) {
|
||||
@Override
|
||||
boolean preCondition() {
|
||||
return mVolUpAndDownMute;
|
||||
}
|
||||
@Override
|
||||
void execute() {
|
||||
triggerVirtualKeypress(KeyEvent.KEYCODE_VOLUME_MUTE);
|
||||
}
|
||||
@Override
|
||||
void cancel() {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mKeyCombinationManager.addRule(
|
||||
new TwoKeysCombinationRule(KEYCODE_VOLUME_DOWN, KEYCODE_VOLUME_UP) {
|
||||
@Override
|
||||
boolean preCondition() {
|
||||
return mAccessibilityShortcutController
|
||||
.isAccessibilityShortcutAvailable(isKeyguardLocked());
|
||||
}
|
||||
@Override
|
||||
void execute() {
|
||||
interceptAccessibilityShortcutChord();
|
||||
}
|
||||
@Override
|
||||
void cancel() {
|
||||
cancelPendingAccessibilityShortcutAction();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Volume up + power can either be the "ringer toggle chord" or as another way to
|
||||
// launch GlobalActions. This behavior can change at runtime so we must check behavior
|
||||
|
|
@ -3391,6 +3414,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
|
|||
mCameraLaunch = LineageSettings.System.getIntForUser(resolver,
|
||||
LineageSettings.System.CAMERA_LAUNCH, 0,
|
||||
UserHandle.USER_CURRENT) == 1;
|
||||
mVolUpAndDownMute = LineageSettings.System.getIntForUser(resolver,
|
||||
LineageSettings.System.VOLUME_UP_AND_DOWN_MUTE, 0,
|
||||
UserHandle.USER_CURRENT) == 1;
|
||||
|
||||
// Configure wake gesture.
|
||||
boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
|
||||
|
|
|
|||
|
|
@ -263,6 +263,8 @@ import com.android.internal.util.ArrayUtils;
|
|||
import com.android.internal.util.FastPrintWriter;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.internal.util.function.pooled.PooledLambda;
|
||||
import com.android.internal.util.custom.BypassUtils;
|
||||
import com.android.internal.util.custom.PixelPropsUtils;
|
||||
import com.android.server.LocalManagerRegistry;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemConfig;
|
||||
|
|
@ -1791,7 +1793,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
*/
|
||||
@Override
|
||||
public void preloadRecentsActivity(Intent intent) {
|
||||
enforceTaskPermission("preloadRecentsActivity()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("preloadRecentsActivity()");
|
||||
}
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mGlobalLock) {
|
||||
|
|
@ -2005,7 +2009,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public void setFocusedRootTask(int taskId) {
|
||||
enforceTaskPermission("setFocusedRootTask()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("setFocusedRootTask()");
|
||||
}
|
||||
ProtoLog.d(WM_DEBUG_FOCUS, "setFocusedRootTask: taskId=%d", taskId);
|
||||
final long callingId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
|
|
@ -2027,7 +2033,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public void setFocusedTask(int taskId) {
|
||||
enforceTaskPermission("setFocusedTask()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("setFocusedTask()");
|
||||
}
|
||||
final long callingId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mGlobalLock) {
|
||||
|
|
@ -2040,7 +2048,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public void focusTopTask(int displayId) {
|
||||
enforceTaskPermission("focusTopTask()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("focusTopTask()");
|
||||
}
|
||||
final long callingId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mGlobalLock) {
|
||||
|
|
@ -2147,7 +2157,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public Rect getTaskBounds(int taskId) {
|
||||
enforceTaskPermission("getTaskBounds()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("getTaskBounds()");
|
||||
}
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
Rect rect = new Rect();
|
||||
try {
|
||||
|
|
@ -2433,7 +2445,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public void moveTaskToRootTask(int taskId, int rootTaskId, boolean toTop) {
|
||||
enforceTaskPermission("moveTaskToRootTask()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("moveTaskToRootTask()");
|
||||
}
|
||||
synchronized (mGlobalLock) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
|
|
@ -2469,7 +2483,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
*/
|
||||
@Override
|
||||
public void removeRootTasksInWindowingModes(int[] windowingModes) {
|
||||
enforceTaskPermission("removeRootTasksInWindowingModes()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("removeRootTasksInWindowingModes()");
|
||||
}
|
||||
|
||||
synchronized (mGlobalLock) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
|
|
@ -2483,7 +2499,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public void removeRootTasksWithActivityTypes(int[] activityTypes) {
|
||||
enforceTaskPermission("removeRootTasksWithActivityTypes()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("removeRootTasksWithActivityTypes()");
|
||||
}
|
||||
|
||||
synchronized (mGlobalLock) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
|
|
@ -2514,7 +2532,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public List<RootTaskInfo> getAllRootTaskInfos() {
|
||||
enforceTaskPermission("getAllRootTaskInfos()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("getAllRootTaskInfos()");
|
||||
}
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mGlobalLock) {
|
||||
|
|
@ -2527,7 +2547,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public RootTaskInfo getRootTaskInfo(int windowingMode, int activityType) {
|
||||
enforceTaskPermission("getRootTaskInfo()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("getRootTaskInfo()");
|
||||
}
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mGlobalLock) {
|
||||
|
|
@ -2540,7 +2562,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public List<RootTaskInfo> getAllRootTaskInfosOnDisplay(int displayId) {
|
||||
enforceTaskPermission("getAllRootTaskInfosOnDisplay()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("getAllRootTaskInfosOnDisplay()");
|
||||
}
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mGlobalLock) {
|
||||
|
|
@ -2554,7 +2578,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
@Override
|
||||
public RootTaskInfo getRootTaskInfoOnDisplay(int windowingMode, int activityType,
|
||||
int displayId) {
|
||||
enforceTaskPermission("getRootTaskInfoOnDisplay()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("getRootTaskInfoOnDisplay()");
|
||||
}
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mGlobalLock) {
|
||||
|
|
@ -2567,7 +2593,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public void startSystemLockTaskMode(int taskId) {
|
||||
enforceTaskPermission("startSystemLockTaskMode");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("startSystemLockTaskMode");
|
||||
}
|
||||
// This makes inner call to look as if it was initiated by system.
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
|
|
@ -2593,7 +2621,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
*/
|
||||
@Override
|
||||
public void stopSystemLockTaskMode() throws RemoteException {
|
||||
enforceTaskPermission("stopSystemLockTaskMode");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("stopSystemLockTaskMode");
|
||||
}
|
||||
stopLockTaskModeInternal(null, true /* isSystemCaller */);
|
||||
}
|
||||
|
||||
|
|
@ -2888,7 +2918,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public void resizeTask(int taskId, Rect bounds, int resizeMode) {
|
||||
enforceTaskPermission("resizeTask()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("resizeTask()");
|
||||
}
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mGlobalLock) {
|
||||
|
|
@ -3117,7 +3149,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
/** Unregister a task stack listener so that it stops receiving callbacks. */
|
||||
@Override
|
||||
public void unregisterTaskStackListener(ITaskStackListener listener) {
|
||||
enforceTaskPermission("unregisterTaskStackListener()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("unregisterTaskStackListener()");
|
||||
}
|
||||
mTaskChangeNotificationController.unregisterTaskStackListener(listener);
|
||||
}
|
||||
|
||||
|
|
@ -3330,6 +3364,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
}
|
||||
|
||||
static void enforceTaskPermission(String func) {
|
||||
|
||||
if (BypassUtils.shouldBypassPermission(Binder.getCallingUid())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkCallingPermission(MANAGE_ACTIVITY_TASKS) == PackageManager.PERMISSION_GRANTED) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -3927,7 +3966,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public void cancelTaskWindowTransition(int taskId) {
|
||||
enforceTaskPermission("cancelTaskWindowTransition()");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("cancelTaskWindowTransition()");
|
||||
}
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (mGlobalLock) {
|
||||
|
|
@ -4230,7 +4271,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
*/
|
||||
@Override
|
||||
public void clearLaunchParamsForPackages(List<String> packageNames) {
|
||||
enforceTaskPermission("clearLaunchParamsForPackages");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("clearLaunchParamsForPackages");
|
||||
}
|
||||
synchronized (mGlobalLock) {
|
||||
for (int i = 0; i < packageNames.size(); ++i) {
|
||||
mTaskSupervisor.mLaunchParamsPersister.removeRecordForPackage(packageNames.get(i));
|
||||
|
|
@ -4240,7 +4283,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public void onPictureInPictureUiStateChanged(PictureInPictureUiState pipState) {
|
||||
enforceTaskPermission("onPictureInPictureUiStateChanged");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("onPictureInPictureUiStateChanged");
|
||||
}
|
||||
synchronized (mGlobalLock) {
|
||||
// The PictureInPictureUiState is sent to current pip task if there is any
|
||||
// -or- the top standard task (state like entering PiP does not require a pinned task).
|
||||
|
|
@ -6774,7 +6819,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||
|
||||
@Override
|
||||
public void startConfirmDeviceCredentialIntent(Intent intent, Bundle options) {
|
||||
enforceTaskPermission("startConfirmDeviceCredentialIntent");
|
||||
if (!PixelPropsUtils.shouldBypassTaskPermission(mContext)) {
|
||||
enforceTaskPermission("startConfirmDeviceCredentialIntent");
|
||||
}
|
||||
|
||||
synchronized (mGlobalLock) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue